DataGridview ComboBox 变化结果
DataGrdiview ComboBox change result
我的项目有一个带有 Combobox 列的 DataGridView,此列有两个项目,如“Punch Window”和“Window Wall”,如图所示。
我正在使用 dataGridView1_CellEndEdit 活动,这些是我的代码
for (int i = 0; i < dgv_MaliyetCalismasi.Rows.Count; i++)
{
if (dgv_MaliyetCalismasi.Rows[i].Cells["col_numberofProduct"].Value != null)
{
if (dgv_MaliyetCalismasi.Rows[i].Cells["col_numberofProduct"].Value.ToString() == "PUNCH WINDOW")
{
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].Value = "No entry";
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].ReadOnly = true;
}
else
{
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].Value = null;
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].ReadOnly = false;
}
}
}
当我选择 Punch Window(A 列)然后选择另一列(B 列)return“无条目”。当我选择 A 列“Window Wall”B 列 returns null 时,一切正常,直到这里。
我的问题是当 A 列选择“Window Wall”项目时,我尝试在 B 列中输入一些数据,然后 dataGridView1_CellEndEdit 事件开始并再次使 B 列为空。
我怎样才能防止这种情况。选择 Window Wall 后,我想处理 cellandedit 事件或希望 B 列单元格独立运行。我希望用户可以在 B 列单元格中输入数据。
提前致谢enter image description here
我经常看到人们将他们的模型与他们的显示方式(视图)交织在一起。
您应该将模型与视图分开。
如果您将数据与数据的显示方式分开,然后您决定更改模型的显示方式,例如从 Forms 到 WPF,则模型中不会发生更改。如果您决定更改模型,例如,从 XML 序列化更改为数据库,则您的视图不必更改。
模型和视图的分离还使对模型进行单元测试变得更加容易:您无需启动 Forms 程序即可查看是否正确处理了模型。
我的土耳其语有点生疏,但在我看来,您想显示一个 MaliyetCalismasi
序列,其中每个 MaliyetCalismasi
至少有一个 Number
,一个 ProductType
和一个 Pcs
,不管是什么。
乍一看,ProductType 和 Pcs 好像有关系。似乎如果 ProductType 等于“Punch Window”,那么 Pcs 应该是“No Entry”,如果 ProductType 等于“Window Wall”,那么 Pcs 等于 null。
显然以上内容无效:可以将 Pcs 更改为“No Entry”和 null 以外的其他值。如果操作员在 Pcs 中键入不同的值,则您没有指定 ComboBox 的值:显示空 ComboBox?显示原始值?
您应该决定:您制作 ProductType
只是因为我希望能够在我的 DataGridView 中进行 ComboBox 选择,还是因为它是模型的一部分而制作它:如果您不愿意不必在 DataGridView 中显示数据,您还会有“ProductType”吗?
型号
我不确定 ProductType 是否可以有超过这两个值。让我们假设不是。如果它可以有更多的值,你应该改变类型。
enum ProductType
{
PunchWindow,
WindowWall,
... // other Values?
}
class MaliyetCalismasi
{
public int Number {get; set;}
public string Pcs {get; set;}
// TODO: ProductType
}
我们知道如果有人将 ProductType 设置为 ProductType.PunchWindow,属性 件会发生什么。但是,如果有人更改 Pcs,ProductType 会发生什么吗?
private ProductType productType = ProductType.WindowWall;
public ProductType ProductType
{
get => this.productType;
set
{
if (this.ProductType != value)
{
this.productType = value;
this.OnProductTypeChanged();
}
}
}
private void OnProductTypeChanged()
{
const string pcsPuncWhindowValue = "No Entry";
if (this.ProductType == ProductType.PunchWindow}
{
this.Pcs = pcsPunchWindowValue;
}
else
{
this.Pcs = null;
}
}
如果 Pcs 改变了,你想要 ProductType 做什么?没有什么?还是第三个值?
private string pcs = null;
public string Pcs
{
get => this.pcs
set
{
if (this.Pcs != value)
{
this.pcs = value;
this.OnPcsChanged();
}
}
}
顺便说一下,您是否看到因为我创建了 On...Changed 方法,所以 PropertyChanged 事件的实现将相当容易。
对此 class 进行单元测试的工作量很小。
很容易看出,如果将来您决定添加一个新的 ProductType 值“ManualSelected”,这意味着如果有人更改 Pcs,ProductType 将获得该值,那么更改将是最小的。
显示 MaliyetCalismasi
人们倾向于直接编辑 DataGridView 中的单元格。如果你想这样做,请再考虑一下。如果您仍然认为需要它,那就去做吧。使用 DataSource 更容易。
// Create the DataGridView and the add the columns
DataGridView dataGridView1 = new DataGridView();
DataGridViewColumn columnNumber = new DataGridViewColumn();
DataGridViewColumn columnPcs = new DataGridViewColumn();
DataGridViewComboBoxColumn columnProductType = new DataGridViewComboBoxColumn();
// which properties should these column show?
columnNumber.DataPropertyName = nameof(MaliyetCalismasi.Number);
columnPcs.DataPropertyName = nameof(MaliyetCalismasi.Pcs);
columnProductType.DataPropertyName = nameof(MaliyetCalismasi.ProductType);
通常以上是使用 visual studio 设计器完成的。您还需要做一些特殊的事情来填充 ComboBox。这不是这个问题的一部分。
现在只做一个显示,您需要做的就是将数据分配给 DataGridView 的数据源:
List<MaliyetCalismasi> fetchedMaliyetCalismasi = this.FetchMaliyetCalismasi();
this.dataGridView1.DataSource = fetchedMaliyetCalismasi;
这将是仅显示:如果操作员更改显示的数据:更改单元格、添加或删除行,原始数据不会更新。
如果你想要更新的数据,你需要把数据放在一个实现了IBindingList的对象中,比如BindingList(显而易见的名字):
this.dataGridView.DataSource = new BindingList<MaliyetCalismasi>
(fetchedMaliyetCalismasi);
很快!每个编辑过的单元格都会在 BindingList 中自动更新,即使添加或删除了行也是如此。即使操作员对显示的行进行排序,或重新排列列。这是因为您将视图与模型分开:显示已更改,但模型未更改。
将数据与其显示方式分开的良好做法将导致以下过程:
BindingList<MaliyetCalismasi> MaliyetCalismasi
{
get => (BindingList<MaliyetCalismasi>)this.DataGridView1.DataSource;
set => this.DataGridView1.DataSource = value;
}
IEnumerable<MaliyetCalismasi> FetchMaliyetCalismasi()
{
// TODO implement, fetch from database, or Json, or internet, or whatever
}
void InitDataGridView
{
this.MaliyetCalismasi = new BindingList<MaliyetCalismasi>(
this.FetchMaliyetCalismasi().ToList());
}
如果您想对选定的行执行某些操作:
MaliyetCalismasi CurrentMaliyetCalismasi =>
this.DataGridView1.CurrentRow?.DataBoundItem as MaliyetCalismasi;
IEnumerable<MaliyetCalismasi> SelectedMaliyetCalismasi =>
this.DataGridView1.SelectedRows
.Select(row => row.DataBoundItem)
.Cast<MaliyetCalismasi>();
你看,因为你将模型与其显示方式分开,所以处理数据显示主要由单行方法组成!
意大利面 kadar kolay!
我的项目有一个带有 Combobox 列的 DataGridView,此列有两个项目,如“Punch Window”和“Window Wall”,如图所示。
我正在使用 dataGridView1_CellEndEdit 活动,这些是我的代码
for (int i = 0; i < dgv_MaliyetCalismasi.Rows.Count; i++)
{
if (dgv_MaliyetCalismasi.Rows[i].Cells["col_numberofProduct"].Value != null)
{
if (dgv_MaliyetCalismasi.Rows[i].Cells["col_numberofProduct"].Value.ToString() == "PUNCH WINDOW")
{
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].Value = "No entry";
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].ReadOnly = true;
}
else
{
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].Value = null;
dgv_MaliyetCalismasi.Rows[i].Cells["col_pcs"].ReadOnly = false;
}
}
}
当我选择 Punch Window(A 列)然后选择另一列(B 列)return“无条目”。当我选择 A 列“Window Wall”B 列 returns null 时,一切正常,直到这里。
我的问题是当 A 列选择“Window Wall”项目时,我尝试在 B 列中输入一些数据,然后 dataGridView1_CellEndEdit 事件开始并再次使 B 列为空。 我怎样才能防止这种情况。选择 Window Wall 后,我想处理 cellandedit 事件或希望 B 列单元格独立运行。我希望用户可以在 B 列单元格中输入数据。
提前致谢enter image description here
我经常看到人们将他们的模型与他们的显示方式(视图)交织在一起。 您应该将模型与视图分开。
如果您将数据与数据的显示方式分开,然后您决定更改模型的显示方式,例如从 Forms 到 WPF,则模型中不会发生更改。如果您决定更改模型,例如,从 XML 序列化更改为数据库,则您的视图不必更改。
模型和视图的分离还使对模型进行单元测试变得更加容易:您无需启动 Forms 程序即可查看是否正确处理了模型。
我的土耳其语有点生疏,但在我看来,您想显示一个 MaliyetCalismasi
序列,其中每个 MaliyetCalismasi
至少有一个 Number
,一个 ProductType
和一个 Pcs
,不管是什么。
乍一看,ProductType 和 Pcs 好像有关系。似乎如果 ProductType 等于“Punch Window”,那么 Pcs 应该是“No Entry”,如果 ProductType 等于“Window Wall”,那么 Pcs 等于 null。
显然以上内容无效:可以将 Pcs 更改为“No Entry”和 null 以外的其他值。如果操作员在 Pcs 中键入不同的值,则您没有指定 ComboBox 的值:显示空 ComboBox?显示原始值?
您应该决定:您制作 ProductType
只是因为我希望能够在我的 DataGridView 中进行 ComboBox 选择,还是因为它是模型的一部分而制作它:如果您不愿意不必在 DataGridView 中显示数据,您还会有“ProductType”吗?
型号
我不确定 ProductType 是否可以有超过这两个值。让我们假设不是。如果它可以有更多的值,你应该改变类型。
enum ProductType
{
PunchWindow,
WindowWall,
... // other Values?
}
class MaliyetCalismasi
{
public int Number {get; set;}
public string Pcs {get; set;}
// TODO: ProductType
}
我们知道如果有人将 ProductType 设置为 ProductType.PunchWindow,属性 件会发生什么。但是,如果有人更改 Pcs,ProductType 会发生什么吗?
private ProductType productType = ProductType.WindowWall;
public ProductType ProductType
{
get => this.productType;
set
{
if (this.ProductType != value)
{
this.productType = value;
this.OnProductTypeChanged();
}
}
}
private void OnProductTypeChanged()
{
const string pcsPuncWhindowValue = "No Entry";
if (this.ProductType == ProductType.PunchWindow}
{
this.Pcs = pcsPunchWindowValue;
}
else
{
this.Pcs = null;
}
}
如果 Pcs 改变了,你想要 ProductType 做什么?没有什么?还是第三个值?
private string pcs = null;
public string Pcs
{
get => this.pcs
set
{
if (this.Pcs != value)
{
this.pcs = value;
this.OnPcsChanged();
}
}
}
顺便说一下,您是否看到因为我创建了 On...Changed 方法,所以 PropertyChanged 事件的实现将相当容易。
对此 class 进行单元测试的工作量很小。
很容易看出,如果将来您决定添加一个新的 ProductType 值“ManualSelected”,这意味着如果有人更改 Pcs,ProductType 将获得该值,那么更改将是最小的。
显示 MaliyetCalismasi
人们倾向于直接编辑 DataGridView 中的单元格。如果你想这样做,请再考虑一下。如果您仍然认为需要它,那就去做吧。使用 DataSource 更容易。
// Create the DataGridView and the add the columns
DataGridView dataGridView1 = new DataGridView();
DataGridViewColumn columnNumber = new DataGridViewColumn();
DataGridViewColumn columnPcs = new DataGridViewColumn();
DataGridViewComboBoxColumn columnProductType = new DataGridViewComboBoxColumn();
// which properties should these column show?
columnNumber.DataPropertyName = nameof(MaliyetCalismasi.Number);
columnPcs.DataPropertyName = nameof(MaliyetCalismasi.Pcs);
columnProductType.DataPropertyName = nameof(MaliyetCalismasi.ProductType);
通常以上是使用 visual studio 设计器完成的。您还需要做一些特殊的事情来填充 ComboBox。这不是这个问题的一部分。
现在只做一个显示,您需要做的就是将数据分配给 DataGridView 的数据源:
List<MaliyetCalismasi> fetchedMaliyetCalismasi = this.FetchMaliyetCalismasi();
this.dataGridView1.DataSource = fetchedMaliyetCalismasi;
这将是仅显示:如果操作员更改显示的数据:更改单元格、添加或删除行,原始数据不会更新。
如果你想要更新的数据,你需要把数据放在一个实现了IBindingList的对象中,比如BindingList(显而易见的名字):
this.dataGridView.DataSource = new BindingList<MaliyetCalismasi>
(fetchedMaliyetCalismasi);
很快!每个编辑过的单元格都会在 BindingList 中自动更新,即使添加或删除了行也是如此。即使操作员对显示的行进行排序,或重新排列列。这是因为您将视图与模型分开:显示已更改,但模型未更改。
将数据与其显示方式分开的良好做法将导致以下过程:
BindingList<MaliyetCalismasi> MaliyetCalismasi
{
get => (BindingList<MaliyetCalismasi>)this.DataGridView1.DataSource;
set => this.DataGridView1.DataSource = value;
}
IEnumerable<MaliyetCalismasi> FetchMaliyetCalismasi()
{
// TODO implement, fetch from database, or Json, or internet, or whatever
}
void InitDataGridView
{
this.MaliyetCalismasi = new BindingList<MaliyetCalismasi>(
this.FetchMaliyetCalismasi().ToList());
}
如果您想对选定的行执行某些操作:
MaliyetCalismasi CurrentMaliyetCalismasi =>
this.DataGridView1.CurrentRow?.DataBoundItem as MaliyetCalismasi;
IEnumerable<MaliyetCalismasi> SelectedMaliyetCalismasi =>
this.DataGridView1.SelectedRows
.Select(row => row.DataBoundItem)
.Cast<MaliyetCalismasi>();
你看,因为你将模型与其显示方式分开,所以处理数据显示主要由单行方法组成!
意大利面 kadar kolay!