绑定到parent's DataContext中的依赖属性

本文关键字:DataContext 依赖 属性 parent 绑定 | 更新日期: 2023-09-27 18:15:44

我想将第三列绑定到CollectionBindingTwo属性,该属性在windows的DataContext内,而不是在CollectionBindingOne的项目的DataContext内。

通过在<DataGrid>中定义第二个集合,WPF假定局部作用域或其他东西,并指向ItemsSource (CollectionBindingOne)的Items中的属性。

<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>

绑定到parent's DataContext中的依赖属性

DataGridComboBoxColumn不是Visual Tree的一部分,所以通常的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的顶部声明helper命名空间import

这就是[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>