【问题标题】:Populate ComboBox of a DataGrid with values from another column使用来自另一列的值填充 DataGrid 的 ComboBox
【发布时间】:2016-10-03 18:52:27
【问题描述】:

我是一位经验丰富的 Winforms 用户,我现在正在使用 WPF,但我有点挣扎。 我有一个包含 2 列的数据网格。 第一列是绑定到我的对象的“名称”属性的 DataGridTextColumn。 第二列绑定到我的对象的“Power”属性。

当用户编辑电源列时,我想显示一个组合框,其中列出了第一列的所有名称以及“无”作为第一项。 我该怎么做?

此外,如果用户更新第一列的任何名称,我希望更改反映在 Power 列中。有可能吗?

在后面的代码中:

public partial class MainWindow : Window
{
    ObservableCollection<MyObject> objects = new ObservableCollection<MyObject>();

    public MainWindow()
    {
        InitializeComponent();
        dgObjects.ItemsSource = objects;
    }
}

public class MyObject
{   
    public String Name { get; set; }
    public String Power { get; set; }
}

在 Xaml 中:

<DataGrid Name="dgObjects" AutoGenerateColumns="False">
   <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        <DataGridComboBoxColumn Header="Power" Binding="????"/>
    </DataGrid.Columns>
</DataGrid>

谢谢

【问题讨论】:

  • 您可以在其他地方设置和维护您的集合,通常与包含要绑定数据网格的项目集合的级别相同,然后通过更改 @ 将 ComboBox.ItemsSource 绑定到该集合987654324@的绑定。在最常见的场景中,RelativeSource 绑定用于查找父 DataGrid 并绑定到 DataGrid.DataContext.SomeCollection。例如,ItemsSource="{Binding DataContext.PowerValues, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"

标签: wpf validation data-binding datagrid datagridcomboboxcolumn


【解决方案1】:

您可以通过绑定DataContext 来做到这一点。不过,首先您需要正确设置窗口的DataContextItemsSource 不应该通过代码隐藏来完成(这是 WPF,使用绑定!)。

设置你的类结构,如:

  public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ViewModel();
        }
    }

    public class ViewModel
    {
        public ObservableCollection<MyObject> Objects { get; } = new ObservableCollection<MyObject>();

        public ViewModel()
        {
            Objects.Add(new MyObject
            {
                Name = "Name"
            });
            Objects.Add(new MyObject
            {
                Name = "Name2"
            });
            Objects.Add(new MyObject
            {
                Name = "Name3"
            });
        }
    }

    public class MyObject
    {
        public String Name { get; set; }
        public String Power { get; set; }
    }

现在,更新您的 xaml。您将需要使用CellTemplate 和标准Combobox。然后ComboBox 将绑定到 Objects 集合,显示名称,但在 Power 中设置值。

<Window x:Class="WpfApplication8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        x:Name="MyWindow">
    <Grid>
        <DataGrid Name="dgObjects" AutoGenerateColumns="False"
                  ItemsSource="{Binding Objects}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding ElementName=MyWindow, Path=DataContext.Objects}" 
                                      DisplayMemberPath="Name"
                                      SelectedItem="{Binding Power}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

【讨论】:

  • 是的,我也推荐这样的东西,尽管我会使用 RelativeSource 绑定而不是 ElementName 绑定,具体取决于 UI 层次结构
  • @Rachel 使用 RelativeSource 是否存在性能问题/好处?
  • 使用 ElementName 可能比遍历可视化树要快一些,但我认为这还不够重要。如果我们搜索的话,我敢肯定有人在网上某处做了一些测试:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
相关资源
最近更新 更多