我有三个网格视图
网格视图1包含这些列
IdProject;IdItem;长数量
网格视图2包含以下列
IdInventory;IdItem;长可用数量
网格视图3包含以下列
IdProject;IdInventory;IdItem;长预留数量;不可用数量
操作是这样的:
我比较网格视图1和网格视图2的(IdItem,Length,Quantity(如果匹配,我有两个选项:
- 数量<=QuantityAvailable
我将一行添加到网格视图3(ReservedQuantity=数量,Unavailable Quantity=0( - 数量>QuantityAvailable
我有两个选项:
a-网格视图2:匹配的行不是最后一行
将一行添加到网格视图3(ReservedQuantity=QuantityAvailableandUnavailable Quantity=0(,然后继续到下一个匹配行
b-网格视图2:匹配/不匹配的行是最后一行
我将一行增加到网格视图3(预留数量((
我习惯使用此代码
int[] selectedRows = gridView1.GetSelectedRows();
for (int i = 0; i < selectedRows.Length; i++)
{
DataRow rowGridView1 = (gridView1.GetRow(selectedRows[i]) as DataRowView).Row;
for (int j = 0; j < gridView2.RowCount; j++)
{
//check for comparison
//add rows
}
}
刚接触DataGridView的人倾向于直接摆弄DataGridView中的单元格,尽管使用DataSource要容易得多。
你写道:操作是这样的:我将网格视图1中的(IdItem、Length、Quantity(与网格视图2进行比较。
遗憾的是,网格视图1没有(IdItem,Length,Quantity(。但是,此DataGridView中的每一行都有。我想你是想比较Dgv 中的行
我想你的意思是,将Dgv1的第0行与Dgv2的第0行将进行比较,并根据值从Dgv3创建第0行。类似地,你对所有行都这样做。
显然Dgv1显示了一系列相似的项目。我不知道它们是什么,所以假设它们是a类的物品。这个类类似于以下内容:
class A
{
public int IdProject {get; set;}
public int IdItem {get; set;}
public decimal Length {get; set;}
public int Quantity {get; set;}
}
类似地,Dgv2显示类别B:的项目
class B
{
public int IdInventory {get; set;}
public int IdItem {get; set;}
public decimal Length {get; set;}
public int QuantityAvailable {get; set;}
}
Dgv3显示类C:
class C
{
public int IdProject {get; set;}
public int IdInventory {get; set;}
public int IdItem {get; set;}
public decimal Length {get; set;}
public int ReservedQuantity {get; set;}
public int UnavailableQuantity {get; set;}
}
您的类可能有其他几个属性,或其他标识符或类型,但您了解要点。
使用visualstudio设计器,您添加了三个DataGridViews和列。在构造函数中,您可以提到哪个列应该显示哪个属性。
为此,我们使用属性DataGridViewColumn.DataPropertyName
// constructor
public MyForm()
{
InitializeComponent();
// Dgv1 shows properties of class A
dgv1ColumnIdProject.DataPropertyName = nameof(A.IdProject);
dgv1ColumnIdItem.DataPropertyName = nameof(A.IdItem);
dgv1ColumnLength.DataPropertyName = nameof(A.Length);
dgv1ColumnQuantity.DataPropertyName = nameof(B.Length);
// Dgv2 shows properties of class B
dgv2ColumnIdInventory.DataPropertyName = nameof(B.IdInventory);
... // etc also Dgv3 and class C
}
在某些地方,您有方法来获取应该显示在Dgv1和Dgv2:中的数据
(As是A的复数;Bs是B的复数等(
private IEnumerable<A> FetchAsToDisplay() {...}
private IEnumerable<B> FetchBsToDisplay() {...}
要填充DataGridViews并获取DataGridVies中的项目,请创建以下属性:
private BindingList<A> DisplayedAs
{
get => (BindingList<A>)this.Dgv1.DataSource;
set => this.Dgv1.DataSource = value;
}
private BindingList<B> DisplayedBs
{
get => (BindingList<B>)this.Dgv2.DataSource;
set => this.Dgv2.DataSource = value;
}
private BindingList<C> DisplayedCs
{
get => (BindingList<C>)this.Dgv3.DataSource;
set => this.Dgv3.DataSource = value;
}
现在,要用它们的初始值填充Dgv1和Dgv2,请执行以下操作:
IEnumerable<A> asToDisplay = this.FetchAsToDisplay();
this.DisplayedAs = new BindingList<A>(asToDisplay.ToList());
IEnumerable<B> bsToDisplay = this.FetchBsToDisplay();
this.DisplayedBs = new BindingList<B>(bsToDisplay.ToList());
要计算Dgv3中应该包含的内容,您可以重用asToDisplay和bsToDisplay,或者如果以后必须这样做,例如在单击按钮OK后:
private void OnButtonOk_Clicked(object sender, ...)
{
ICollection<A> displayedAs = this.DisplayedAs;
ICollection<B> displayedBs = this.DisplayedBs;
IEnumerable<C> csToDisplay = this.CreateCsToDisplay(displayedAs, displayedBs);
this.DisplayedCs = new BindingList(csToDisplay.ToList();
}
CreateCsToDisplay(TODO:发明一个更好的名称(是根据您定义的两个选项来决定应该显示什么的过程。
private IEnumerable<C> CreateCsToDisplay(IEnumerable<A> as, IEnumerable<B> bs)
{
// assume Dgv1 and Dgv2 has the same number of rows,
// so sequence as has the same number of elements as sequence bs
// use ZIP to combine A and B. For every [a,b] combination create a C:
return as.Zip(bs, (a, b) => this.CreateC(a, b);
}
private C CreateC(A a, B b)
{
// use the conditions you defined
if (a.Quantity < b.QuantityAvailable)
{
return new C
{
ReservedQuantity = a.Quantity,
UnavailableQuantity = 0,
};
}
else
{
return new C ... etc, see your specification
}
}
摘要
通过使用DataSource和BindingList,您不必再摆弄Rows和Cells,您可以将Rows解释为类似项的序列。使用类似DisplayedAs
的属性来访问这些行。获取和设置显示的项目现在是小菜一碟:只需使用属性即可。
为了计算如何从一个[A,B]组合中创建一个C,我们创建了一个方法CreateC。此方法隐藏您的规范。
类似地,我们有一种方法可以从As和Bs的序列创建Cs序列:CreateCsToDisplay。此方法还隐藏了创建Cs的方式。