我希望有人可以帮助我解决一个让我完全陷入困境的晦涩难题。
我希望设置一个DataGridView,它允许用户从DataGridViewComboBoxColumn中选择一个选项,并使用用户在ComboBox中选择的对象来更新DataGridView的数据源对象。 / p>
[我希望DataGridViewComboBoxColumn在下拉列表中显示多个属性,因此我使用DataTable作为DataGridViewComboBoxColumn数据源。换句话说,我希望他们看到一个描述,它是连接在一起的其他属性的组合。]
我的代码有效,但是当我在ComboBox单元格外部单击时,该值会自动设置(它将被设置回BindingList中的第一个项目)。我无法坚持用户选择的价值。最终,错误的对象实例被分配给DataGridView的dataSource。
我会张贴一张照片,但我没有足够的代表。
所以我的问题是,当我在单元格外部单击时,为什么DataGridViewComboBoxColumn会切换到其数据源中的第一项(DataTable)。如何让它在单元格中保留我选择的选项。我绝对是BAFFLED。
我希望可以将这么多代码发布到StackOverflow网站,而不会让每个人烦恼。我试图创建适当的通用示例,以帮助任何其他灵魂尝试找出如何使用DataGridViewComboBoxColumn选择并将对象分配给另一个对象的属性。所以希望这对其他人有用。如果有人需要解决这类问题,我也试图让它重新创建起来相对容易。
我尝试了各种各样的方法,包括使用List作为DataGridViewComboBoxColumn的数据源,使用CurrentCellDirtyStateChanged事件做事 - 一切都无济于事。
这是我的两个班级:
public class CarPartChoice
{
public string Name { get; set; }
public int Value { get; set; }
public string Comment {get; set;}
public CarPartChoice(string name, int value, string comment)
{
Name = name;
Value = value;
Comment = comment;
}
}
public class Car
{
public string Manufacturer { get; set; }
public string Model { get; set; }
public CarPartChoice WheelChoice {get; set;}
public Car(string maker, string model, CarPartChoice wheel)
{
Manufacturer = maker;
Model = model;
WheelChoice = wheel;
}
public Car(string maker, string model)
{
Manufacturer = maker;
Model = model;
}
}
public static class GlobalVariables
{
public static BindingList<CarPartChoice> GlobalChoiceList { get; set; }
public static BindingList<Car> GlobalCarsList { get; set; }
}
这是我创建dataGridView:
private void Form1_Load(object sender, EventArgs e)
{
//Setup the wheel choices to be selected from the DataGridViewComboBoxColumn.
CarPartChoice myWheelChoice = new CarPartChoice("Chrome", 19, "This is the chromes wheels option.");
CarPartChoice myWheelChoice2 = new CarPartChoice("HubCaps", 16, "This is the nasty plastic hubcaps option.");
BindingList<CarPartChoice> tempBLChoice = new BindingList<CarPartChoice>();
tempBLChoice.Add(myWheelChoice);
tempBLChoice.Add(myWheelChoice2);
GlobalVariables.GlobalChoiceList = tempBLChoice;
//Setup the cars to populate the datagridview.
Car car1 = new Car("Vauxhall", "Astra");
Car car2 = new Car("Mercedes", "S-class");
BindingList<Car> tempListCars = new BindingList<Car>();
tempListCars.Add(car1);
tempListCars.Add(car2);
GlobalVariables.GlobalCarsList = tempListCars;
dataGridView1.AutoGenerateColumns = false;
dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged);
// Set up 2 DataGridViewTextBox columns, one to show the manufacturer and the other to show the model.
DataGridViewTextBoxColumn manufacturer_col = new DataGridViewTextBoxColumn();
manufacturer_col.DataPropertyName = "Manufacturer";
manufacturer_col.Name = "Manufacturer";
manufacturer_col.HeaderText = "Manufacturer";
DataGridViewTextBoxColumn model_col = new DataGridViewTextBoxColumn();
model_col.DataPropertyName = "Model";
model_col.Name = "Model";
model_col.HeaderText = "Model";
// Create a DataTable to hold the Wheel options available for the user to choose from. This DT will be the DataSource for the
// ...combobox column
DataTable wheelChoices = new DataTable();
DataColumn choice = new DataColumn("Choice", typeof(CarPartChoice));
DataColumn choiceDescription = new DataColumn("Description", typeof(String));
wheelChoices.Columns.Add(choice);
wheelChoices.Columns.Add(choiceDescription);
foreach (CarPartChoice wheelchoice in GlobalVariables.GlobalChoiceList)
{
wheelChoices.Rows.Add(wheelchoice, wheelchoice.Name + " - " + wheelchoice.Value.ToString() + " - " + wheelchoice.Comment);
}
// Create the Combobox column, populated with the wheel options so that user can pick one.
DataGridViewComboBoxColumn wheelOption_col = new DataGridViewComboBoxColumn();
wheelOption_col.DataPropertyName = "WheelChoice";
wheelOption_col.Name = "WheelChoice";
wheelOption_col.DataSource = wheelChoices;
wheelOption_col.ValueMember = "Choice";
wheelOption_col.DisplayMember = "Description";
wheelOption_col.ValueType = typeof(CarPartChoice);
// Add the columns and set the datasource for the DGV.
dataGridView1.Columns.Add(manufacturer_col);
dataGridView1.Columns.Add(model_col);
dataGridView1.Columns.Add(wheelOption_col);
dataGridView1.DataSource = GlobalVariables.GlobalCarsList;
}
更新: 我试图使用“BindingSource”对象并将BindingSource的数据源设置为DataTable。这没有任何区别。我也尝试让Car实现“INotifyPropertyChanged”界面,这没有任何区别。
如果我注意到的一件事是datagridview中的Car项目会更新其WheelChoice属性。使用从ComboBox中选择的值更新Car对象IS INDEED。我认为这只是一个显示问题,DataGridViewComboBoxColumn只是没有填充正确的值。仍然感到困惑。
答案 0 :(得分:0)
感谢那些发表评论的人。我最终找到了答案。
答案是我只需为我的“CarPartChoice”类定义一个重写的“ToString()”方法(即用于通过单击ComboBoxColumn来提供要查找的项目的类)。我想当我把控件移开时,用一个很好的字符串格式化我的单元格时遇到了麻烦。
因此,对于将来想要这样做的任何人,这里有一个完整的示例,说明如何使用datagridview更新某个类的对象列表,并使用DataGridViewComboBoxColumn为用户提供选择对象以及它们所选择的对象(它们从下拉列表中选择)将被填充到列表中(准确地说:在列表中对象的字段中,该对象是由用户选择的对象类型)下拉)。是的,我知道这是一个非常可怕的判决。
这是完成此任务的完整代码(我原本认为这是人们经常想做的事情。)
对所有人表示最诚挚的问候。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Setup the wheel choices to be selected from the DataGridViewComboBoxColumn.
CarPartChoice myWheelChoice = new CarPartChoice("Chrome", 19, "This is the chromes wheels option.");
CarPartChoice myWheelChoice2 = new CarPartChoice("HubCaps", 16, "This is the nasty plastic hubcaps option.");
CarPartChoice myWheelChoice3 = new CarPartChoice("Iron", 15, "These are metal wheels.");
CarPartChoice myWheelChoice4 = new CarPartChoice("Spoked", 15, "This is the fancy classic hubcaps option.");
CarPartChoice myWheelChoice5 = new CarPartChoice("solid", 13, "This wheels has no spokes or holes.");
CarPartChoice myWheelChoice6 = new CarPartChoice("SpaceHubCaps", 17, "Newly developed space hubcaps.");
BindingList<CarPartChoice> tempBLChoice = new BindingList<CarPartChoice>();
tempBLChoice.Add(myWheelChoice);
tempBLChoice.Add(myWheelChoice2);
tempBLChoice.Add(myWheelChoice3);
tempBLChoice.Add(myWheelChoice4);
tempBLChoice.Add(myWheelChoice5);
tempBLChoice.Add(myWheelChoice6);
GlobalVariables.GlobalChoiceList = tempBLChoice;
//Setup the cars to populate the datagridview.
Car car1 = new Car("Vauxhall", "Astra");
Car car2 = new Car("Mercedes", "S-class");
BindingList<Car> tempListCars = new BindingList<Car>();
tempListCars.Add(car1);
tempListCars.Add(car2);
GlobalVariables.GlobalCarsList = tempListCars;
dataGridView1.AutoGenerateColumns = false;
dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged);
// Set up 2 DataGridViewTextBox columns, one to show the manufacturer and the other to show the model.
DataGridViewTextBoxColumn manufacturer_col = new DataGridViewTextBoxColumn();
manufacturer_col.DataPropertyName = "Manufacturer";
manufacturer_col.Name = "Manufacturer";
manufacturer_col.HeaderText = "Manufacturer";
DataGridViewTextBoxColumn model_col = new DataGridViewTextBoxColumn();
model_col.DataPropertyName = "Model";
model_col.Name = "Model";
model_col.HeaderText = "Model";
// Create a DataTable to hold the Wheel options available for the user to choose from. This DT will be the DataSource for the
// ...combobox column
DataTable wheelChoices = new DataTable();
DataColumn choice = new DataColumn("Choice", typeof(CarPartChoice));
DataColumn choiceDescription = new DataColumn("Description", typeof(String));
wheelChoices.Columns.Add(choice);
wheelChoices.Columns.Add(choiceDescription);
foreach (CarPartChoice wheelchoice in GlobalVariables.GlobalChoiceList)
{
wheelChoices.Rows.Add(wheelchoice, wheelchoice.Name + " - " + wheelchoice.Value.ToString() + " - " + wheelchoice.Comment);
}
// Create the Combobox column, populated with the wheel options so that user can pick one.
DataGridViewComboBoxColumn wheelOption_col = new DataGridViewComboBoxColumn();
wheelOption_col.DataPropertyName = "WheelChoice";
wheelOption_col.DataSource = wheelChoices;
wheelOption_col.ValueMember = "Choice";
wheelOption_col.DisplayMember = "Description";
wheelOption_col.ValueType = typeof(CarPartChoice);
// Add the columns and set the datasource for the DGV.
dataGridView1.Columns.Add(manufacturer_col);
dataGridView1.Columns.Add(model_col);
dataGridView1.Columns.Add(wheelOption_col);
dataGridView1.DataSource = GlobalVariables.GlobalCarsList;
}
void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
var grid = sender as DataGridView;
if (grid.IsCurrentCellDirty)
grid.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
public class CarPartChoice
{
public string Name { get; set; }
public int Value { get; set; }
public string Comment { get; set; }
public CarPartChoice(string name, int value, string comment)
{
Name = name;
Value = value;
Comment = comment;
}
public override string ToString()
{
return Name.ToString() + " - " + Value.ToString() + " - " + Comment.ToString();
}
}
public class Car
{
public string Manufacturer { get; set; }
public string Model {get; set; }
public CarPartChoice WheelChoice { get; set; }
public Car(string maker, string model, CarPartChoice wheel)
{
Manufacturer = maker;
Model = model;
WheelChoice = wheel;
}
public Car(string maker, string model)
{
Manufacturer = maker;
Model = model;
}
}
public static class GlobalVariables
{
public static BindingList<CarPartChoice> GlobalChoiceList { get; set; }
public static BindingList<Car> GlobalCarsList { get; set; }
}
答案 1 :(得分:0)
我也遇到相同的问题,但数据集不同。我试图将一个键值对添加到组合框,并且每次我在外面单击时,它都会重置为第一项。我所缺少的是我没有设置组合框的displayMember属性。 (希望这对其他遇到相同问题的人有所帮助)