如何使用 DataSource 绑定将数组字段映射到 WinForms DataGridView 中的多个列?

How do I map an array field to multiple columns in a WinForms DataGridView using a DataSource binding?

我有一个 class 这样的:

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;
}

我想将 "Prices" 映射到 DataGridView 中的 "Price 1"、"Price 2" 等列。我可以显示列,但不知道如何使映射工作。

这是主要内容 window:

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

    public MainForm()
    {
        InitializeComponent();

        SetupPricingData();
        SetupGridView();
    }

    private void SetupPricingData()
    {
        _records = new BindingList<PricingRecord>();

        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,但这似乎不支持将许多列映射到数组。

我发现我可以通过绘制来处理定价列。我需要的用途是只读的,所以这是我现在的解决方案:

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;
                }
            }
        }
    }
}

事实证明,一个更快、更灵活的解决方案是删除 BindingList 并直接戳网格中的单元格。将数组字段映射到多个列的需求变得没有实际意义,因为它是手工完成的。