【问题标题】:Datagrid ComboBox binding two valuesDatagrid ComboBox 绑定两个值
【发布时间】:2014-05-28 19:06:15
【问题描述】:

我有一个组合框,它是从从 Observable 集合中选择获得的名称列表中填充的。但是,与这些名称相关联的是该 Observable 集合中的 ID。目标是当用户选择一个新名称(说将“John”更改为“Jill”)时,我将能够获得 ID,而不仅仅是名称。我能想到的唯一方法是以某种方式将 ID 也存储在组合框中。但我不知道如何通过绑定来做到这一点。

<DataGridTemplateColumn Header="Name ">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox  x:Name="namescombo" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.Names}" 
                          SelectedItem="{Binding Name,  UpdateSourceTrigger=PropertyChanged}" FontSize="12" Background="White" FontFamily="Cambria" BorderBrush="White" BorderThickness="0"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

C#

ObservableCollection<Name> Names = new ObservableCollection<Name>();       
Name twofields = new Name();
        var NamesQuery =
           from p in dataEntities.Names

           select new { p.Name, p.Id };

        foreach (var p in NamesQuery)
        {


            Names.Add(new Name
                {
            ID = p.Id,
            Name = p.Name

                });

        }
 Names = Names.Select(p => p.Name).Distinct().ToList();

【问题讨论】:

  • 你在使用 MVVM 模式吗?
  • DataContext.Names的数据类型是什么?是字符串枚举还是Name对象枚举?
  • 只是从可观察集合中选择的字符串的枚举

标签: c# wpf datagrid combobox


【解决方案1】:

ComboBox 包含DisplayMemberPathSelectedValuePath 的属性,因此您可以使用它告诉ComboBox 通过"Id" 属性识别项目,但将"Name" 属性显示为用户。

例如,

<DataGridTemplateColumn Header="Name ">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox 
                ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.Names}" 
                DisplayMemberPath="Name"
                SelectedValuePath="Id"
                SelectedValue="{Binding SelectedId}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

我建议使用 SelectedValue 而不是 SelectedItem,因为 WPF 将 SelectedItem.Equals() 进行比较,默认情况下按引用比较项目,并且如果您的 SelectedItem 与 @ 中的项目不完全相同的引用987654333@,不会被选中。

例如,SelectedItem = new Person(1, "Test"); 可能不会正确设置所选项目,而 SelectedItem = ItemsSource[0] 会因为它引用存在于 ItemsSource 中的项目。

此外,将所选项目的Id 存储在一行而不是整个对象通常更有意义:)

【讨论】:

  • 我不同意这里。在这种情况下可能会很好。但理想选择的对象应该始终是 ItemsSource 的一部分。 (显然,除非 comboBox 是可编辑的并允许用户输入值)
  • @RohitVats 我在使用 Entity Framework 时经常遇到这个问题,因为 ComboBox 项目是通过在一次调用期间读取数据库中的表获得的,而项目显示在每一行中(包括 SelectedRecord从链接表获得的属性)正在第二次数据库调用期间创建。
  • 谢谢。这对我帮助很大。我还有一个问题。如何在我的代码中访问 SelectedValuePath?现在,我目前正在使用 DataGrid.CurrentItem 来获取其余的值,但不知道如何获取这个值。
  • @user3481541 DataGrid.SelectedItem 它将是行本身的对象,您可以将其转换为项目的数据类型并获取它的Id 属性。像这样:((MyItem)DataGrid.SelectedItem).Id。无论如何,你需要这个做什么?在 WPF 中从 UI 访问这样的项目是不正常的,并且可能有更好的方法来完成您正在使用它执行的任务。
  • 我们有一个非规范化表,其中 fID、fName 都存在,但 fID 是唯一的。但是,用户没有看到 fID 也没有更改它,他们只看到 fName 并更改了它。但是,一旦 fName 更改,fID 就是应该更新的内容。我想,我可以通过加入表格本身来完成同样的事情。那会是更好的选择吗?
【解决方案2】:

您可以直接绑定到 Name 对象集合并将 DisplayMemberPath 设置为 Name 属性,以便字符串显示在 GUI 上,但本质上,您已将完整的对象绑定到组合框。

这样您可以将 SelectedItem 绑定到 Name 对象,并可以访问 Id 和 Name 属性。

<ComboBox ItemsSource="{Binding Names}" // Collection of name objects.
          DisplayMemberPath="Name"
          SelectedItem="{Binding SelectedNameObject}"/> // Object of type Name.

【讨论】:

    猜你喜欢
    • 2013-03-22
    • 1970-01-01
    • 2020-07-20
    • 2021-07-07
    • 1970-01-01
    • 2014-10-10
    • 2011-05-06
    • 2021-03-29
    • 1970-01-01
    相关资源
    最近更新 更多