我正在尝试将DataGridView与业务对象一起使用。这是一个简化的场景:
-调用对象“配方”,它在配方中具有几个成分对象的BindingList
-我还有一个“数据库”,它是所有可用成分对象的BindingList
我想显示配方中所有成分的DataGridView,并允许用户从“名称”字段中的组合框中选择新的成分。
当我尝试以我认为应该的方式进行设置时,尽管可以从IngredientDB中进行选择,但不会显示配方中成分的名称,并且选择新的成分确实会更新配方中的列表。
如何获得正确显示的名称?
这是我到目前为止的内容:
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApplication1 {
public class Ingredient {
private String name;
public String Name {
get { return name; }
set { name = value; }
}
private string description;
public String Description {
get { return description; }
set { description = value; }
}
private int amount;
public int Amount {
get { return amount; }
set { amount = value; }
}
public Ingredient(String n, String d, int a) {
Name = n;
Description = d;
Amount = a;
}
public Ingredient() { }
}
public class Data {
BindingList<Ingredient> ingredientDB = null;
public BindingList<Ingredient> IngredientDB {
get { return ingredientDB; }
}
public Data() {
ingredientDB = new BindingList<Ingredient>();
ingredientDB.Add(new Ingredient("rice", "a grain", 2));
ingredientDB.Add(new Ingredient("whole wheat flour", "for baking", 1));
ingredientDB.Add(new Ingredient("butter", "fatty", 3));
}
}
public class Recipe : INotifyPropertyChanged {
public String Name {
get;
set;
}
BindingList<Ingredient> ingredients = null;
public BindingList<Ingredient> Ingredients {
get { return ingredients; }
set {
ingredients = value;
NotifyPropertyChanged("Ingredients");
}
}
public Recipe() {
Ingredients = new BindingList<Ingredient>();
Ingredients.Add(new Ingredient("Water", "Wet", 2));
Ingredients.Add(new Ingredient("Gin", "Yummy", 2));
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
public class myForm : Form {
private DataGridView dgv;
private BindingSource recipeBS;
private BindingSource dataBS;
public myForm() {
this.Height = 200;
this.Width = 400;
Recipe myRecipe = new Recipe();
Data myData = new Data();
recipeBS = new BindingSource(myRecipe, null);
dataBS = new BindingSource(myData, "IngredientDB");
dgv = new DataGridView();
dgv.Width = 400;
dgv.DataError += new
DataGridViewDataErrorEventHandler(DataGridView1_DataError);
dgv.DataSource = myRecipe.Ingredients;
// dgv.Columns.Remove("Name");
DataGridViewComboBoxColumn comboboxColumn = new DataGridViewComboBoxColumn();
comboboxColumn.DataPropertyName = "Name";
comboboxColumn.HeaderText = "Name";
comboboxColumn.DataSource = dataBS;
comboboxColumn.DisplayMember = "Name";
comboboxColumn.ValueMember = "Name";
dgv.Columns.Insert(0, comboboxColumn);
this.Controls.Add(dgv);
}
private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs anError) { }
[STAThreadAttribute()]
static void Main() {
Application.EnableVisualStyles();
Application.Run(new myForm());
}
}
}
最佳答案
您的“ ingredientDB”列表中没有水或杜松子酒成分。 DataGridView的数据源设置为成分列表。加载表单后,它将根据业务对象的属性(即成分)自动创建3列(名称,说明,金额)。然后,根据您的“成分”列表(“水”和“金酒”)添加行。因此,最终结果是,DataGridView中有3列和2行,看起来像这样:
Name | Description | Amount
Water | Wet | 2
Gin | Yummy | 2
但是,您正在将DataGridViewComboBoxColumn插入第0列(即第一列),这就是问题所在。
DataGridVidwComboBoxColumn的数据源设置为dataBs BindingSource,而后者又设置为“ ingredientDB”。 “ ingredientDB”仅包含“大米”,“全麦面粉”和“黄油”的条目。当该列显示为第一行时,它将在其数据源(“ ingredientDB”)中查找名称==“ Water”的成分。此“ ingredientDB”不包含水成分,通常会引发DataGridViewDataErrorEvent。但是,您是在自己处理事件,而不对此做任何事情。因此,ComboBox中没有任何内容。 “杜松子酒”成分也会发生相同的情况。在“ ingredientDB”中找不到“金酒”成分,因此无法选择。
要解决此问题,您需要将“ Water”和“ Gin”都添加到“ ingredientDB”中:
public Data()
{
ingredientDB = new BindingList<Ingredient>();
ingredientDB.Add(new Ingredient("rice", "a grain", 2));
ingredientDB.Add(new Ingredient("whole wheat flour", "for baking", 1));
ingredientDB.Add(new Ingredient("butter", "fatty", 3));
ingredientDB.Add(new Ingredient("Water", "Wet", 2));
ingredientDB.Add(new Ingredient("Gin", "Yummy", 2));
}