【问题标题】:Create relationship between two ComboBoxes在两个 ComboBox 之间创建关系
【发布时间】:2019-02-26 01:33:52
【问题描述】:

我有两个相关的表(类别和子类别)。所以我在 Windows 窗体上有 2 个 ComboBox 控件。这 2 个 ComboBox 在父子(或类别子类别)关系中相关。例如,我有一个 ComboBox 包含供用户选择的类别列表(父)和另一个包含子类别列表的 ComboBox(子)。 现在我需要:如果用户从第一个组合框中选择类别,那么在第二个组合框中必须出现与该类别相关的子类别。 例如:

| Category
| cat_id   | cat_name |
| 1        | Car      |
| 2        | Car1     |
| 3        | Car2     |
| 4        | Car3     |

及子类别

| SubCategory
| scat_id   | scat_name  | cat_id |
| 1         | sCar       | 1      |
| 2         | sCar1      | 1      |
| 3         | sCar2      | 3      |
| 4         | sCar3      | 1      |

这是两个相关的表结构。 我有这个 C# 代码:

private void SInfo_Load(object sender, EventArgs e)
{
    using (var context = new StBaseSQLEntities())
    {
        metroComboBox1.DataSource = context.Category.ToList();
        metroComboBox1.DisplayMember = "cat_name";
        metroComboBox1.ValueMember = "cat_id";

        //SubCategory
        metroComboBox2.DataSource = context.SubCategory.ToList();
        metroComboBox2.DisplayMember = "scat_name";
        metroComboBox2.ValueMember = "scat_id";
    }
}

我是 C# Windows 窗体的新手,所以我不知道如何执行此操作。如果我从类别组合框中选择 1,那么我的第二个组合框需要在子类别组合框中显示属于 1st id 的子类别。 如何在 C# win 表单中获得结果?

【问题讨论】:

  • 您必须使用 MetroComboBox1 SelectedIndexChanged 或 SelectedValueChanged 事件来设置 MetroComboBox2 的数据源,使用该值。我猜,那个 DataSource 可能是 LINQ 的 context.SubCategory.Where(x => x.scat_id = metroComboBox1.SelectedValue).ToList()); 类似的东西。

标签: c# winforms


【解决方案1】:

只需使用第一个组合框上的SelectedValue 属性作为子类别的过滤器:

private void MetroComboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
    ComboBox cmb = (ComboBox) sender;
    MetroComboBox2.DataSource = 
                      context.Subcategory.Where(x => x.cat_id == cmb.SelectedValue).ToList();
    MetroComboBox2.enabled = true;
}

【讨论】:

  • 这是对 SelectedIndex 的危险假设。
  • @LarsTech 你是对的......以这种方式引用 id 时会发生令人讨厌的事情。已编辑
【解决方案2】:

...如果 用户从第一个组合框中选择类别,那么在第二个组合框中 组合框必须出现与类别相关的子类别。

使用ComboBox.SelectionChangeCommitted Event
来自文档:

当用户更改所选项目并且该更改是 显示在 ComboBox 中

即使以编程方式更改了选定的值,也会发生其他“更改”事件。

将所有子目录保存为私有成员,这样您就可以在不读取数据库的情况下对其进行过滤。

private List<SubCategory> _allSubCategories;

private void SInfo_Load(object sender, EventArgs e)
{
    using (var context = new StBaseSQLEntities())
    {
        metroComboBox1.DataSource = context.Category.ToList();
        metroComboBox1.DisplayMember = "cat_name";
        metroComboBox1.ValueMember = "cat_id";

        //SubCategory
        _allSubCategories = context.SubCategory.ToList();
        metroComboBox2.DataSource = _allSubCategories;
        metroComboBox2.DisplayMember = "scat_name";
        metroComboBox2.ValueMember = "scat_id";
    }
}

然后在SelectionChangeCommittedeventhandler

private void metroComboBox1_SelectionChangeCommitted(object sender, EventArgs e)
{
    var combobox = (ComboBox)sender;
    var selectedCategory = (short)combobox.SelectedValue;
    metroComboBox.DataSource = 
        _allSubCategories.Where(sub => sub.cat_id == selectedCategory).ToList();
    // display/enable item
}

【讨论】:

  • 谢谢,但我有一个问题,所以在我的表 subcategory.cat_id 中输入 smallint,如果我运行你的变体,我在 var selectedCategory = 中有 InvalidCastException (int)combobox.SelectedValue;
  • 然后投到short
  • 是的,我试过了,但它对我不起作用,短类型不适用于“==”、“.Equals”等数据类型,我也尝试转换为int 32 但它没有帮助。我无法在 where 子句中转换 selectedValue
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 2021-12-25
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多