如何将集合绑定到WPF的DataGridComboBoxColumn?

21
我有一个简单的对象,例如:
class Item
{
  ....

  public String Measure { get; set; }
  public String[] Measures {get; }
}
我正在尝试将其绑定到一个具有两个文本列和一个组合框列的DataGrid。 对于组合框列,属性Measure是当前选择,而Measures是可能的值。
我的XAML如下:
<DataGrid Name="recipeGrid" AutoGenerateColumns="False" 
          CellEditEnding="recipeGrid_CellEditEnding" CanUserAddRows="False"
          CanUserDeleteRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Food" Width="Auto"
                            Binding="{Binding Food.Name}" />
        <DataGridTextColumn Header="Quantity" IsReadOnly="False"
                            Binding="{Binding Quantity}" />

        <DataGridComboBoxColumn Header="Measure" Width="Auto"
                                SelectedItemBinding="{Binding Path=Measure}"
                                ItemsSource="{Binding Path=Measures}" />

    </DataGrid.Columns>
</DataGrid>

文本列可以正常显示,但组合框无法显示值。绑定错误为:

System.Windows.Data Error: 2 : 找不到目标元素的主 FrameworkElement 或 FrameworkContentElement。BindingExpression:Path=Measures; DataItem=null; target element is 'DataGridComboBoxColumn' (HashCode=11497055); target property is 'ItemsSource' (type 'IEnumerable')

我该如何解决?

4个回答

21

这绝对是最好的解决方案:

http://wpfthoughts.blogspot.com/2015/04/cannot-find-governing-frameworkelement.html

思路在于声明一个静态资源 CollectionViewSource,并将其声明性地绑定到 DataGridComboBoxColumn 的 ItemsSource 上。

创建和绑定静态 CollectionViewSource:

 <Page.Resources>
     <CollectionViewSource x:Key="Owners" Source="{Binding Owners}"/>
 </Page.Resources>

然后绑定目标的 ItemsSource:

ItemsSource="{Binding Source={StaticResource Owners}}"

4
简单而有效!如果 CollectionViewSource 没有在其他地方使用,您也可以直接将其放在 <DataGrid.Resources> 中。 - piedar
我知道这是一个旧帖子,但是当ObservableCollection存在于ViewModel而不是View中时,它是如何工作的? - Holden

3

1
那么,如果是这样的话,为什么文本列可以工作,但组合框列却不能呢? - georgiosd
如果我理解正确的话,这是因为文本列直接绑定到DataGrid的ItemsSource属性,DataGrid.ItemsSource->Item->Measure,而ComboBox隐式绑定到项的DataContext,该DataContext不会被继承。DataGrid.ItemsSource->Item->DataContext->Measures/Measure。这就是我的理解,不过我承认我并不擅长解释,可能有人可以比我做得更好。 - ThomasAndersson
1
请注意,Binding不起作用的原因是内部代码动态设置了DataGridColumn.Binding到DataGridCell.Content (http://blogs.msdn.com/b/vinsibal/archive/2009/04/07/5-random-gotchas-with-the-wpf-datagrid.aspx)。 - Maxence

2
如果您的度量标准适用于所有对象,则可以将其设置为静态。
public String[] Measures { get; }

你的XAML将使用以下代码:

<DataGridComboBoxColumn
    Header="Role"
    SelectedValueBinding="{Binding Role}"
    ItemsSource="{Binding Source={x:Static local:ProjectsDataContext.Roles}}"
    DisplayMemberPath="Name"/>

希望这能有所帮助。


0

如果您想将行的数据上下文项绑定到组合框,可以使用带有模板中的 DataGridTemplateColumnComboBox 的方式。请注意,您必须将 Mode=TwoWay, UpdateSourceTrigger=PropertyChanged 属性添加到 SelectedItem 绑定中,否则它将无法正确地更新。

<DataGridTemplateColumn Header="My Stuff">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding MyThings}"
                SelectedItem="{Binding SelectedThing, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接