C# 在 DatagridView 中显示数据?

C# Showing Data in DatagridView?

这是我的表 1

当我点击最后一行时,它在第二个网格控件上显示数据,现在我想在下面的表格中显示这些数据(表格 2(带有橙色的购买表格)) datagridview 我该怎么做这个。

        table.Columns.Add("Item Name", Type.GetType("System.String"));
        table.Columns.Add("Main Qty", Type.GetType("System.Decimal"));
        table.Columns.Add("Price", Type.GetType("System.Decimal"));
        table.Columns.Add("Per", Type.GetType("System.String"));
        table.Columns.Add("Basic Amount", Type.GetType("System.Decimal"));
        table.Columns.Add("Dis Amount", Type.GetType("System.Decimal"));
        table.Columns.Add("Dis Percentage", Type.GetType("System.Decimal"));
        table.Columns.Add("Tax Amount", Type.GetType("System.Decimal"));
        table.Columns.Add("Net Value", Type.GetType("System.Decimal"));
        dataGridView1.DataSource = table;

以上是(form 2)的Form Load

下面是Form 1的RowClick

 private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e)
    {

        try
        {
            FRM_Purchase frm = new FRM_Purchase();

            
           
            var ctx = new BizPlusEntities();
            int GettingIdForShowing = (int)gridView1.GetRowCellValue(e.RowHandle, "PurchaseID");
         
            var GettinginToDatabase = ctx.Purchases.Where(x => x.PurchaseID == GettingIdForShowing).ToList();
            foreach (var item in GettinginToDatabase)
            {
                frm.txtPartyName.Text = item.PartyName;
                frm.txtDate.Text = item.Date.ToString();
                frm.txtTerms.Text = item.Terms;
                frm.txtSeries.Text = item.Series;
                frm.txtDueDate.Text = item.DueDate.ToString();
                frm.txtPinvoice.Text = item.Pinvoice.ToString();
                UniqueIdentifier = item.UniquePurchaseNumber;
                string SelectingUniqueIdentfier = ctx.Purchases.SingleOrDefault(x => x.PurchaseID == item.PurchaseID)?.UniquePurchaseNumber ?? "Nulled";

                var GettingInItems = ctx.ItemPurchaseDatas.Where(x => x.UniquePurchaseNumber == SelectingUniqueIdentfier).ToList();
                foreach (var Sam in GettingInItems)
                {
                    TItemName = Sam.ItemName;
                    TMainQty = Sam.MainQty ?? 0;
                    TPrice = Sam.Price ?? 0;
                    TPer = Sam.Per;
                    TBasicAmount = Sam.BasicAmount ?? 0;
                    TDisAmt = Sam.DisAmount ?? 0;
                    TDisP = Sam.DecimalPercentage ?? 0;
                    TTaxAmount = Sam.Gst ?? 0;
                    TTotalAmount = Sam.TotalAmount ?? 0;

                }


                frm.Show();
            }
        }
        catch (Exception)
        {

            throw;
        }
        
    }

问题是当我在 Form1 上执行 frm.Table.Rows.Add(TItem,TMainQty...) 它显示输入数组比此 table 中的列数长 当我创建一个新列时,它说该列已经存在。

我的建议是将数据与数据显示方式分开。除此之外,这使得对数据处理进行单元测试变得更加容易,它使数据显示者可以自由更改数据的显示方式。

在 WPF 中,这种模型和视图的分离几乎是强制性的,在 Winforms 中,你真的必须注意,否则你将数据处理与显示方式混合在一起,很难改变这一点。

在您的情况下:Form1 是否应该关心数据在 Form2 中的显示方式,是否应该知道 Form2 使用 DataGridView?还是Form1只关心Form2显示什么数据,而不关心格式是什么?

与 Form2 的正确接口应该是,其他 Form 告诉应该显示什么数据,如果数据可以更改,其他 Form 之后可以询问数据的值。像这样:

private void ShowForm2()
{
    var dataToShow = this.FetchDataToShow();
    using (var dlg = new Form2())
    {
        dlg.Data = dataToShow;
        var dlgResult = dlg.ShowDialog(this);
        if (dlgResult == DialogResult.OK)
        {
            var dataToProcess = dlg.Data;
            this.ProcessData(dataToProcess);
        }
    }
}

这样,您只需告诉 Form2 显示什么数据,其他表单并不真正关心 Form2 如何显示其数据。这使 Form2 可以自由更改数据的显示方式。此表单的每个用户都将拥有相同的人机界面。

顺便说一下:您是否注意到我还把 Form1 从哪里获取 Form2 的数据以及它存储结果的地方分开了?此程序也不关心数据在Form1中的显示方式,让您可以自由更改Form1,而不必更改此程序。

使用数据绑定

使用 DataBinding 处理 DataGridView 中的行通常比直​​接访问 DataGridView 的行和单元格更容易。

要使用数据绑定,您的列需要知道您的 Class 中的哪个 属性 应该显示在此列中。这通常在 visual studio 设计器中完成。

在您的情况下,Form2 的 DataGridView 似乎需要显示 ItemPurchaseDatas:DataGridView 中的每一行都会显示一个 ItemPurchaseData 的多个属性。使用 visual studio 设计器您将添加列,并且在每一列中您 select 需要在该列中显示的 属性 的名称:

DataGridView dataGridView1 = new DataGridView();
DataGridViewColumn columnName = new DataGridViewColumn();
columName.HeaderText = "Item Name";
columName.DataPropertyName = nameof(ItemPurchaseData.Name);
...
DataGridViewColumn columnPrice = new DataGridViewColumn();
columnPrice.HeaderText = "Price";
columnPrice.DataPropertyName = nameof(ItemPurchaseData.Price);
...

我们早些时候看到对话框有一个 属性 数据,其中包含要显示的数据。 表单需要一种方法来提取必须在 DataGridView 中显示的 ItemPurchaseDatas:

public IEnumerable<ItemPurchaseData> GetInitialItemPurchaseDatas()
{
    // TODO: use property Data to extract the ItemPurchaseDatas that must be shown
    // in the DataGridView
}

现在你要做的就是在FormLoad的事件处理程序上,获取数据并将其放入dataGridView1的DataSource中:

private void OnFormLoading(object sender, ...)
{
    List<ItemPurchaseData> itemPurchaseDatas = GetInitialItemPurchaseDatas().ToList();
    this.dataGridView1.DataSource = itemPurchaseDatas;
}

这足以显示数据。但是,它将是只读的:操作员所做的任何更改:编辑、添加行、删除行等,都不会反映在 itemPurchaseDatas 中。如果你想要那样,你需要一个实现 IBindingList 的对象,比如 BindingList<T>.

如果您想知道操作员所做的更改,通常明智的做法是添加以下方法:

private BindingList<ItemPurchaseData> DisplayedData
{
    get => (BindingList<ItemPurchaseData>)this.dataGridView1.DataSource;
    set => this.dataGridView1.DataSource = value;
}

现在,操作员对显示数据所做的每项更改:添加/删除行、更改单元格等都会反映在 属性 DisplayedData 中。同样,数据的显示与数据本身是分开的:如果操作员更改了数据显示方式的外观,则对行进行排序、重新排列列对 DisplayedData 没有影响。

如果您经常需要处理 SelectedRows,请考虑添加以下属性:

private ItemPurchaseData CurrentItemPurchaseData =>
    (ItemPurchaseData)this.dataGridView1.CurrentRow?.DataBoundItem;

private IEnumerable<ItemPurchaseData> SelectedItemPurchaseData => 
    this.dataGridView1.DataSource.SelectedRows.Cast<DataGridViewRow>()
        .Select(row => row.DataBoundItem)
        .Cast<ItemPurchaseData>();
    

用法:加载表单时在 DataGridView 中显示数据,按下按钮后处理编辑的数据:

private void OnFormLoading(object sender, ...)
{
    IEnumerable<ItemPurchaseData> itemPurchaseDatas = GetInitialItemPurchaseDatas();
    this.DisplayedData = new BindingList<ItemPurchaseData>(itemPurchaseDatas.ToList());
}

private void OnButtonOk_Clicked(object sender, ...)
{
    ICollection<ItemPurchaseData> editedData = this.DisplayedData;
    // if needed: check which items are changed
    this.ProcessChangedData(editedData);
}

再次说明:由于视图和模型的分离,视图中的代码是一行的

如果只想显示数据,那就是