DataSourceバインディングを使用して、WinForms DataGridViewの配列フィールドを複数の列にマップする方法を教えてください。

私はこのようなクラスがあります:

public class PricingRecord
{
    private string _name;
    private float[] _prices;

    public PricingRecord(string name, float[] prices)
    {
        _name = name;
        _prices = prices;
    }

    [DisplayName("Name")]
    public string PricingName => _name;

    public float[] Prices => _prices;
}

DataGridViewの "Price"を "Price 1"、 "Price 2"などの列にマッピングしたい列を表示させることはできますが、マッピングを機能させる方法がわかりません。

これがメインウィンドウです。

public partial class MainForm : Form
{
    private int _numPricingColumns;
    private BindingList _records;

    public MainForm()
    {
        InitializeComponent();

        SetupPricingData();
        SetupGridView();
    }

    private void SetupPricingData()
    {
        _records = new BindingList();

        for (int i = 0; i < 100; i++)
        {
            var pricing = new PricingRecord($"Name {i + 1}", new [] { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f });
            _records.Add(pricing);
        }

        _numPricingColumns = _records[0].Prices.Length;

        GridView.DataSource = _records;
    }

    private void SetupGridView()
    {
        //GridView.AutoGenerateColumns = false;

        //DataGridViewColumn column = new DataGridViewTextBoxColumn
        //{
       //   Name = "Name",
       //   DataPropertyName = "PricingName"
        //};
        //GridView.Columns.Add(column);

        for (int i = 0; i < _numPricingColumns; i++)
        {
            DataGridViewColumn column = new DataGridViewTextBoxColumn
            {
                Name = $"Price {i + 1}",
                DataPropertyName = $"Price{i + 1}"
            };
            GridView.Columns.Add(column);
        }
    }
}

BindingViewを使用しない場合は、手動ですべて設定できますが、その場合は行と列を自分で管理する必要があります。 BindingViewを使用したいのですが、これは多数の列を配列にマッピングすることをサポートしているようには見えません。

0

6 答え

それらを描画することで価格設定列を処理できるようになりました。私が必要としていた使用法はreadonlyなのでこれが今のところ私の解決策です:

private void OnCellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    for (int i = 0; i < _numPricingColumns; i++)
    {
        var name = $"Price {i + 1}";

        var column = GridView.Columns[name];

        if (column.Index == e.ColumnIndex && e.RowIndex >= 0)
        {
            var row = GridView.Rows[e.RowIndex];
            var record = row.DataBoundItem as PricingRecord;
            if (record != null)
            {
                var selected = (e.State & DataGridViewElementStates.Selected) != 0;
                using (var brush = new SolidBrush(selected ? e.CellStyle.SelectionForeColor : e.CellStyle.ForeColor))
                {
                    e.PaintBackground(e.ClipBounds, selected);
                    e.Graphics.DrawString(record.Prices[i].ToString("N"), e.CellStyle.Font, brush,
                        e.CellBounds.X + 2.0f, e.CellBounds.Y + 2.0f, StringFormat.GenericDefault);
                    e.Handled = true;
                }
            }
        }
    }
}
0
追加された

それらを描画することで価格設定列を処理できるようになりました。私が必要としていた使用法はreadonlyなのでこれが今のところ私の解決策です:

private void OnCellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    for (int i = 0; i < _numPricingColumns; i++)
    {
        var name = $"Price {i + 1}";

        var column = GridView.Columns[name];

        if (column.Index == e.ColumnIndex && e.RowIndex >= 0)
        {
            var row = GridView.Rows[e.RowIndex];
            var record = row.DataBoundItem as PricingRecord;
            if (record != null)
            {
                var selected = (e.State & DataGridViewElementStates.Selected) != 0;
                using (var brush = new SolidBrush(selected ? e.CellStyle.SelectionForeColor : e.CellStyle.ForeColor))
                {
                    e.PaintBackground(e.ClipBounds, selected);
                    e.Graphics.DrawString(record.Prices[i].ToString("N"), e.CellStyle.Font, brush,
                        e.CellBounds.X + 2.0f, e.CellBounds.Y + 2.0f, StringFormat.GenericDefault);
                    e.Handled = true;
                }
            }
        }
    }
}
0
追加された

それらを描画することで価格設定列を処理できるようになりました。私が必要としていた使用法はreadonlyなのでこれが今のところ私の解決策です:

private void OnCellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    for (int i = 0; i < _numPricingColumns; i++)
    {
        var name = $"Price {i + 1}";

        var column = GridView.Columns[name];

        if (column.Index == e.ColumnIndex && e.RowIndex >= 0)
        {
            var row = GridView.Rows[e.RowIndex];
            var record = row.DataBoundItem as PricingRecord;
            if (record != null)
            {
                var selected = (e.State & DataGridViewElementStates.Selected) != 0;
                using (var brush = new SolidBrush(selected ? e.CellStyle.SelectionForeColor : e.CellStyle.ForeColor))
                {
                    e.PaintBackground(e.ClipBounds, selected);
                    e.Graphics.DrawString(record.Prices[i].ToString("N"), e.CellStyle.Font, brush,
                        e.CellBounds.X + 2.0f, e.CellBounds.Y + 2.0f, StringFormat.GenericDefault);
                    e.Handled = true;
                }
            }
        }
    }
}
0
追加された

より速く、より柔軟な解決策はBindingListを削除し、直接グリッド内のセルを突くことであることが証明されました。配列フィールドを複数の列にマップする必要性は、手作業で行われるため問題になります。

0
追加された

より速く、より柔軟な解決策はBindingListを削除し、直接グリッド内のセルを突くことであることが証明されました。配列フィールドを複数の列にマップする必要性は、手作業で行われるため問題になります。

0
追加された

より速く、より柔軟な解決策はBindingListを削除し、直接グリッド内のセルを突くことであることが証明されました。配列フィールドを複数の列にマップする必要性は、手作業で行われるため問題になります。

0
追加された