C# 如何在WinForms中绑定多对多关系?

C# 如何在WinForms中绑定多对多关系?,c#,winforms,data-binding,ado.net,dataset,C#,Winforms,Data Binding,Ado.net,Dataset,我有以下数据集: 可以使用以下DataGridView编辑产品和零件表: 当用户双击产品网格中的一行时,将打开以下表单: 左栏应列出与本产品相关的零件。右栏应该列出所有其他部分。使用>按钮,用户应该能够选择属于当前产品的零件 我做过类似的一对多关系,效果非常好。守则如下: public partial class ProductPartsForm : Form { private int _productID; private DataSet1 _data; pu

我有以下数据集:

可以使用以下DataGridView编辑
产品
零件
表:

当用户双击产品网格中的一行时,将打开以下表单:

左栏应列出与本产品相关的零件。右栏应该列出所有其他部分。使用>按钮,用户应该能够选择属于当前产品的零件

我做过类似的一对多关系,效果非常好。守则如下:

public partial class ProductPartsForm : Form
{
    private int _productID;
    private DataSet1 _data;

    public ProductPartsForm(DataSet1 data, DataRowView productRowView)
    {
        var productRow = (DataSet1.ProductRow)productRowView.Row;
        _productID = productRow.ID;
        _data = data;
        InitializeComponent();
        productBindingSource.DataSource = productRowView;
        assignedPartBindingSource.DataSource = productBindingSource;
        assignedPartBindingSource.DataMember = "FK_Product_Part";
        assignedPartsListBox.DisplayMember = "Name";
        unassignedPartBindingSource.DataSource = _data;
        unassignedPartBindingSource.DataMember = "Part";
        unassignedPartsListBox.DisplayMember = "Name";
        unassignedPartBindingSource.Filter = $"isnull(ProductID, 0) = 0";
    } 

    private void assignButton_Click(object sender, EventArgs e)
    {
        var partRowView = (DataRowView)unassignedPartBindingSource.Current;
        var partRow = (DataSet1.PartRow)partRowView.Row;
        var productRowView = (DataRowView)productBindingSource.Current;
        var productRow = (DataSet1.ProductRow)productRowView.Row;
        partRow.ProductRow = productRow;
        UpdateUI();
    }

    private void unassignButton_Click(object sender, EventArgs e)
    {
        var partRowView = (DataRowView)assignedPartBindingSource.Current;
        var partRow = (DataSet1.PartRow)partRowView.Row;
        partRow.SetProductIDNull();
        UpdateUI();
    }

    private void UpdateUI()
    {
        assignedPartsListBox.Refresh();
        unassignedPartsListBox.Refresh();
        assignButton.Enabled = unassignedPartsListBox.Items.Count > 0;
        unassignButton.Enabled = assignedPartsListBox.Items.Count > 0;
    }
}
在多对多关系中,有两件事我无法去工作:

  • 左列不显示零件的名称。它应该显示小写字母,如右栏;相反,它显示字符串
    System.Data.DataRowView
    。我想通过某种查找来解决这个问题,但我不知道如何解决

  • 当你按下
    时,我终于想到了这一点。关键功能是
    UpdateFilters
    ,它创建分配给当前产品的零件ID列表,然后使用
    IN
    NOT IN
    运算符“手动”过滤两列

    public partial class ProductPartsForm : Form
    {
        private int _productID;
        private DataSet1 _data;
    
        public ProductPartsForm(DataSet1 data, DataRowView productRowView)
        {
            var productRow = (DataSet1.ProductRow)productRowView.Row;
            _productID = productRow.ID;
            _data = data;
            InitializeComponent();
            productBindingSource.DataSource = productRowView;
            assignedPartBindingSource.DataSource = _data;
            assignedPartBindingSource.DataMember = "Part";
            assignedPartsListBox.DisplayMember = "Name";
            unassignedPartBindingSource.DataSource = _data;
            unassignedPartBindingSource.DataMember = "Part";
            unassignedPartsListBox.DisplayMember = "Name";
        }
    
        private void ProductPartsForm_Load(object sender, EventArgs e)
        {
            UpdateFilters();
            UpdateUI();
        }
    
        private void assignButton_Click(object sender, EventArgs e)
        {
            var partRowView = (DataRowView)unassignedPartBindingSource.Current;
            var partRow = (DataSet1.PartRow)partRowView.Row;
            var productRowView = (DataRowView)productBindingSource.Current;
            var productRow = (DataSet1.ProductRow)productRowView.Row;
            _data.ProductPart.AddProductPartRow(productRow, partRow);
            UpdateFilters();
            UpdateUI();
        }
    
        private void unassignButton_Click(object sender, EventArgs e)
        {
            var partRowView = (DataRowView)assignedPartBindingSource.Current;
            var partRow = (DataSet1.PartRow)partRowView.Row;
            var productPartRow = _data.ProductPart
                .Single(pp => pp.ProductID == _productID && pp.PartID == partRow.ID);
            _data.ProductPart.RemoveProductPartRow(productPartRow);
            UpdateFilters();
            UpdateUI();
        }
    
        private void UpdateFilters()
        {
            var assignedIds = _data.ProductPart
                .Where(pp => pp.ProductID == _productID)
                .Select(pp => pp.PartID.ToString());
            if (assignedIds.Any())
            {
                assignedPartBindingSource.Filter = $"ID IN ({string.Join(",", assignedIds)})";
                unassignedPartBindingSource.Filter = $"ID NOT IN ({string.Join(",", assignedIds)})";
            }
            else
            {
                assignedPartBindingSource.Filter = "FALSE";
                unassignedPartBindingSource.RemoveFilter();
            }
        }
    
        private void UpdateUI()
        {
            assignedPartsListBox.Refresh();
            unassignedPartsListBox.Refresh();
            assignButton.Enabled = unassignedPartsListBox.Items.Count > 0;
            unassignButton.Enabled = assignedPartsListBox.Items.Count > 0;
        }
    }
    

    如果您可以发布单独的问题,而不是将您的问题合并为一个问题,这是首选。这样,它可以帮助人们回答你的问题,也可以帮助其他人寻找至少一个你的问题。谢谢我不知道如何把它分解。我有点希望能有某种教科书上的方法来解决整个问题;类似于UI的主细节样式,但适用于多对多关系,而不是一对多关系。我会尽量缩小范围。好吧,你至少应该用这个问题来显示
    按钮的点击事件处理程序,以及
    productBindingSource
    引用的表。“我试图重新表述这个问题。新问题在这里。”,请不要问重复的问题!删除副本并使用副本信息编辑此问题