【问题标题】:Each row (object) with own binding source in datagridview?datagridview 中的每一行(对象)都有自己的绑定源?
【发布时间】:2012-06-23 13:41:58
【问题描述】:

我正在用 C# (.NET 4.0) 编写一个小型应用程序。我有一个datagridview,每一行代表一个对象。我想要一个允许选择该对象的特定属性的组合框列。

示例:

public class Car
{
   public String Make {get; set;}
   public BindingList<String> AllColors {get; set;}
   public int SelectedColorIndex {get; set;}
}

每一行代表一个 Car 对象。每个(不同的)汽车对象都有自己的可能颜色选择(AllColors)。我想要一列,您可以通过从 AllColors 中选择一种颜色来设置 SelectedColorIndex(AllColors 特定于每个 Car 对象)。

注意:我编写了这个示例,但它描述了我想要完成的任务。

我怎样才能做到这一点?我发现的唯一解决方案是在 datagridview 之外有一个特定的组合框,您可以使用它来更改选定的行。在行输入事件中,我将绑定源的数据源更改为当前的“AllColors”。

感谢您的时间和回答。

【问题讨论】:

  • 所以您希望每辆车的组合框提供一组不同的颜色?每辆车的颜色是所有可用颜色的子集吗?
  • 是的。每辆车都有自己的可用颜色,它们不是任何“更大的可用颜色”集的子集。 (这只是我的例子,每个对象都有自己的一组可用属性,这些属性也是对象。我制作了这个例子以使事情更简单)。
  • 我会有一个例子,希望能很快回答这个问题。原型制作大约进行到一半。

标签: c# datagridview bindingsource


【解决方案1】:

这是一个工作示例背后的代码,其中可用颜色被过滤为绑定对象的 AllColors 列表中提供的颜色。

魔术发生在CellBeginEditCellEndEdit 事件处理程序中 - 我们为每个组合框单元格提供绑定行中的列表,然后在退出时将其重置。

这依赖于一个包含所有颜色的主列表 - 没有办法解决这个问题。

我还为新行需要默认值的情况添加了处理。我所做的只是将选定的索引默认设置为一个。当然这在现实世界中是行不通的,你需要一些更聪明的东西! DefaultValuedNeeded 事件是描述 here on MSDN

public partial class Form1 : Form
{

    private BindingSource cars;
    private BindingSource masterColors;

    public Form1()
    {
        InitializeComponent();

        masterColors = new BindingSource();
        masterColors.Add(new CarColor{Name = "Blue", Index = 1});
        masterColors.Add(new CarColor{Name = "Red", Index = 2});
        masterColors.Add(new CarColor { Name = "Green", Index = 3 });
        masterColors.Add(new CarColor { Name = "White", Index = 4 });

        BindingList<CarColor> fordColors = new BindingList<CarColor>();
        fordColors.Add(new CarColor{Name = "Blue", Index = 1});
        fordColors.Add(new CarColor{Name = "Red", Index = 2});

        BindingList<CarColor> toyotaColors = new BindingList<CarColor>();
        toyotaColors.Add(new CarColor { Name = "Green", Index = 3 });
        toyotaColors.Add(new CarColor { Name = "White", Index = 4 });

        cars = new BindingSource();
        cars.Add(new Car { Make = "Ford", SelectedColorIndex = 1, AllColors = fordColors });
        cars.Add(new Car { Make = "Toyota", SelectedColorIndex = 3, AllColors = toyotaColors });

        dataGridView1.DataSource = cars;
        dataGridView1.Columns["SelectedColorIndex"].Visible = false;
        //dataGridView1.Columns["AllColors"].Visible = false;

        DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn();
        col.Name = "AvailableColors";
        col.DataSource = masterColors;
        col.DisplayMember = "Name";
        col.DataPropertyName = "SelectedColorIndex";
        col.ValueMember = "Index";
        dataGridView1.Columns.Add(col);

        dataGridView1.CellBeginEdit += new DataGridViewCellCancelEventHandler(dataGridView1_CellBeginEdit);
        dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);
        dataGridView1.DefaultValuesNeeded += new DataGridViewRowEventHandler(dataGridView1_DefaultValuesNeeded);
    }

    void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
    {
        if (e.ColumnIndex == dataGridView1.Columns["AvailableColors"].Index)
        {
            if (e.RowIndex != dataGridView1.NewRowIndex)
            {
                // Set the combobox cell datasource to the filtered BindingSource
                DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1
                                [e.ColumnIndex, e.RowIndex];
                Car rowCar = dataGridView1.Rows[e.RowIndex].DataBoundItem as Car;
                dgcb.DataSource = rowCar.AllColors;
            }

        }
    }

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == dataGridView1.Columns["AvailableColors"].Index)
        {
            // Reset combobox cell to the unfiltered BindingSource
            DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1
                            [e.ColumnIndex, e.RowIndex];
            dgcb.DataSource = masterColors; //unfiltered
        }
    }

    void dataGridView1_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
    {
        e.Row.Cells["SelectedColorIndex"].Value = 1;
    }

}

public class Car
{
    public String Make { get; set; }
    public BindingList<CarColor> AllColors { get; set; }
    public int SelectedColorIndex { get; set; }
}

public class CarColor
{
    public String Name { get; set; }
    public int Index { get; set; }
}

1 我首先从DataGridView FAQ 中学会了如何做到这一点,这是一个很棒的资源,由当时 Microsoft 的 DataGridView 项目经理 Mark Rideout 编写。 FAQ中的例子是基于另一个combobox过滤的,使用DataTables,但原理是一样的。

【讨论】:

    猜你喜欢
    • 2010-12-15
    • 2020-03-18
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-28
    相关资源
    最近更新 更多