绑定到父级DataContext中的依赖属性

5
我想将第三列绑定到窗口数据上下文中的CollectionBindingTwo属性,而不是CollectionBindingOne的ItemsSource数据上下文中的属性。如果在<DataGrid>中定义第二个集合,WPF会假定它具有本地范围,然后指向CollectionBindingOne的ItemsSource中的属性。
<DataGrid DockPanel.Dock="Top" ItemsSource="{Binding CollectionBindingOne}" AutoGenerateColumns="False">
    <DataGridTextColumn Header="One" Binding="{Binding PropOne}"/>
    <DataGridTextColumn  Header="Two" Binding="{Binding PropTwo}"/>
    <DataGridComboBoxColumn Header="Three" ItemsSource="{Binding CollectionBindingTwo}"/>
</DataGrid>

例如,这个例子可以工作是因为 ComboBox 不在 <DataGrid> 中:
<ComboBox IsEditable="True" ItemsSource="{Binding CollectionBindingTwo}"></ComboBox>
2个回答

3
数据网格组合框列不是视觉树的一部分,因此通常的RelativeSource/ElementName绑定格式不起作用。您可以使用一个解决方法,通过定义ElementStyle和EditingStyle来使用这些绑定格式。另一种选择是使用BindingProxy,我在其他地方使用它并且当没有其他原因定义ElementStyle/EditingStyle时可以节省一些XAML。

这是继承自Freezable的BindingProxy类。

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.
    // This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data",
                                    typeof(object),
                                    typeof(BindingProxy),
                                    new UIPropertyMetadata(null));
}

现在你的XAML看起来像这样:
<DataGrid DockPanel.Dock="Top"
          ItemsSource="{Binding CollectionBindingOne}"
          AutoGenerateColumns="False">
    <DataGrid.Resources>
        <helper:BindingProxy x:Key="proxy"
                             Data="{Binding }" />
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Header="One"
                            Binding="{Binding PropOne}" />
        <DataGridTextColumn Header="Two"
                            Binding="{Binding PropTwo}" />
        <DataGridComboBoxColumn Header="Three" 
                                ItemsSource="{Binding Data.CollectionBindingTwo,
                                              Source={StaticResource proxy}}" />
</DataGrid>

不要忘记在 Window/UserControl 的顶部声明帮助器命名空间的引用。

这个方法可行,感谢您的答案。我选择了样式选项,因为我目前不指望在其他地方需要这样做。如果需要的话,使用您的BindingProxy类会更有意义(也感谢您提供这个建议)。 - Sergey

2

这就是使用[RelativeSource][1]绑定的目的。在这种情况下,您应该能够通过DataGrid的数据上下文来定位父级数据上下文:

<DataGrid>
    <DataGridComboBoxColumn Header="Three" ItemsSource="{Binding  
        RelativeSource={RelativeSource AncestorType=DataGrid},
        Path=DataContext.CollectionBindingTwo}" />
</DataGrid>

ElementName绑定同样也适用:

<DataGrid x:Name="dataGrid">
    <DataGridComboBoxColumn Header="Three" 
        ItemsSource="{Binding ElementName=dataGrid, Path=DataContext.CollectionBindingTwo}" />
</DataGrid>

1
谢谢您的回答。然而,这并没有起作用,很可能是由于Lee的回答中提到的VisualTree成员身份。+1,因为在其他情况下这将起作用,而我不知道您可以从绑定路径访问DataContext。 - Sergey
1
@Sergey 谢谢 - 还可以查看这个答案,使用 x:Reference 的另一种方法:https://dev59.com/NIHba4cB1Zd3GeqPYfyS#25021052 - McGarnagle

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