将数据从网格视图复制到另一个(有没有更好的方法)

Posted

技术标签:

【中文标题】将数据从网格视图复制到另一个(有没有更好的方法)【英文标题】:Copy data from Grid View to another (is there a better way) 【发布时间】:2021-12-09 10:41:35 【问题描述】:

我有三个网格视图 网格视图 1 包含这些列 IdProject ;IdItem ;长度 ;数量

网格视图 2 包含这些列 IdInventory ;IdItem ;Length ;QuantityAvailable

Grid View 3 包含这些列 IdProject ;IdInventory ;IdItem ;Length ;ReservedQuantity ;UnavailableQuantity

操作是这样的: 我将 Grid View1 中的 (IdItem, Length, Quantity) 与 Grid View2 进行比较如果匹配,我有两个选择:

    数量 我在 Grid View3 中添加一行(ReservedQuantity= Quantity 和 UnavailableQuantity=0) 数量 > 数量可用 我有两个选择: a- Grid View2:匹配的行不是最后一个 我在 Grid View3 中添加一行(ReservedQuantity= QuantityAvailable 和 UnavailableQuantity=0)并继续到下一个匹配的行 b- Grid View2:匹配/不匹配的行是最后一个 我在 Grid View3 中添加一行(ReservedQuantity= QuantityAvailable 和 UnavailableQuantity= Quantity-Sum(ReservedQuantity))

我习惯使用这个代码

        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
        
    

【问题讨论】:

你的问题是什么?我们能为您提供什么帮助? 【参考方案1】:

不熟悉 DataGridViews 的人倾向于直接使用 DataGridView 的单元格,尽管使用 DataSource 更容易。

您写道:操作是这样进行的: 我将 Grid View1 中的 (IdItem, Length, Quantity) 与 Grid View2 进行比较。

唉,Grid View1 没有(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;

可能是您的类有几个其他属性,或其他标识符或类型,但您明白了要点。

使用 Visual Studio Designer,您已经添加了三个 DataGridView 和列。在构造函数中,您可以提及哪个列应该显示哪个属性。

为此,我们使用属性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 的创建方式。

【讨论】:

没有足够的语言来表达我对拯救这一天的感激之情。非常感谢。

以上是关于将数据从网格视图复制到另一个(有没有更好的方法)的主要内容,如果未能解决你的问题,请参考以下文章

关于使用 maxscript 将法线从一个网格复制到另一个网格

如何将选定的行从一个 wpf 数据网格复制到另一个 wpf 数据网格? [关闭]

如何使用复制命令在 postgres 中将数据从一个表复制到另一个表

将值从一个 DataGridView 复制到另一个

笔记:实现网格视图数据选择

使用jQuery在多个gridview行中将值从一个文本框复制到另一个文本框