C# WinForms 主从数据绑定中的多个子网格

问题描述 投票:0回答:1

这就是我正在尝试做的事情:

  • VS 2022,.NET Framework 4.8
  • Windows 窗体应用程序
  • 所有数据处理都是DataSets、DataTables等,全部由设计器生成。

在表单上,我有一个 DataGridView(主视图),绑定到 BindingSource,绑定到 DataSet 内的单个 DataTable。

还有一个“详细信息”部分,其中包含绑定到当前主记录中的字段的单独编辑控件(TextBox、DateTimePicker 等)。这一切都很好。

每个“主”行都有两个关联的“子集合”。这些是在数据集设计器中使用“关系和外键约束”连接到父级的附加表中的行。

每个子集合都有一个 DataGridView,绑定到 BindingSource,绑定到主绑定源中的外键关系。

所以,整体表单布局为Parent-Grid、Parent-detail、Child1-Grid、Clild2-Grid。

在查看/编辑记录时,这一切都非常有效,但在尝试创建新记录时,它非常接近工作,但又不完全是。

例如,我添加一个新的主行(通过单击其 BindingNavigator 上的“添加”)。出现行。 我向第一个子集合添加一行(通过单击其 BindingNavigator 上的“添加”)。出现行。我向第二个子集合添加一行。出现行。

我现在编辑详细信息部分中的主字段之一,然后噗!我在子集合中的新行消失了。或者,我单击“保存”保存所有更改,新的子行就会消失。或者我添加多行,当我保存时,最后一行消失。顺便说一句 - 所有这些消失都发生在将 DataSet 保存到数据库之前 - 这是 DataGridView、BindingSource 等之间的所有交互,全部通过设计器生成的代码。

我是否对 Windows 窗体中的数据绑定要求太多,或者在编辑父子集合时是否缺少一些基本的东西?

c# .net winforms data-binding ado.net
1个回答
0
投票

这似乎与数据绑定相关。由于您使用的是 .NET Framework 4.8,因此这里有一些仅基于您的陈述的建议,不包括任何其他限制。

Windows Presentation Foundation:您仍然可以将 WPF 与 .NET Framework 4.8 结合使用。与 Windows 窗体相比,WPF 提供了更好的数据绑定支持和更现代的桌面应用程序构建方法。

这里有一些建议:

  1. 在表单后面的代码中编写处理逻辑的代码。你可以 直接处理数据。请参阅接下来的示例代码。

  2. 您可以尝试 Windows Presentation Foundation。

我还没有看到你的 WinForm 代码,但你可以看一下下面的代码,看看它是否可以引导你走向正确的方向:

//  Plain event-handling sameple.  
using System;
using System.Data;
using System.Windows.Forms;

public partial class MainForm : Form
{
    private DataTable masterTable;
    private DataTable child1Table;
    private DataTable child2Table;

    public MainForm()
    {
        InitializeComponent();
        InitializeData();
        BindMasterGrid();
    }

    private void InitializeData()
    {
        //  This is from your example above
        masterTable = myDataSet.Tables["Master"];
        child1Table = myDataSet.Tables["Child1"];
        child2Table = myDataSet.Tables["Child2"];
    }

    private void BindMasterGrid()
    {
        //  I think your issue is binding related so bind the master 
        //  DataGridView to the master DataTable
        dataGridViewMaster.DataSource = masterTable;

        //  Handle the CurrentCellChanged event to sync child 
        //  DataGridViews with the selected master row
        dataGridViewMaster.CurrentCellChanged += (sender, e) => 
        {
            //  See the code for the next...
            UpdateChildGrids();
        };
    }

    private void UpdateChildGrids()
    {
        //  Get the selectedMasterRow in the grid  
        DataRowView selectedMasterRow = 
        dataGridViewMaster.CurrentRow?.DataBoundItem as DataRowView;
        
        //   This is something to try.  Bind the child DataGridViews
        //   to filtered DataView based on the selected master row
        if (selectedMasterRow != null)
        {
            int masterId = Convert.ToInt32(selectedMasterRow["MasterId"]);

            DataView child1View = new DataView(child1Table);
            child1View.RowFilter = $"MasterId = {masterId}";
            dataGridViewChild1.DataSource = child1View;

            DataView child2View = new DataView(child2Table);
            child2View.RowFilter = $"MasterId = {masterId}";
            dataGridViewChild2.DataSource = child2View;
        }
        else
        {
            //  Clear child DataGridViews if no master row is selected
            dataGridViewChild1.DataSource = null;
            dataGridViewChild2.DataSource = null;
        }
    }

    //  The rest of your code if needed...
}

检查这个答案。希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.