【问题标题】:Bind to a Dependency Property that is in parent's DataContext绑定到父级 DataContext 中的依赖属性
【发布时间】:2014-09-22 07:30:19
【问题描述】:

我想将第三列绑定到 Window 的 DataContext 中的 CollectionBindingTwo 属性,而不是 CollectionBindingOne 的 Items 的 DataContext 中。

通过在<DataGrid> 中定义第二个集合,WPF 假定本地范围或其他东西,并指向 ItemsSource (CollectionBindingOne) 中的一个属性。

<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 不在 &lt;DataGrid&gt; 内:

<ComboBox IsEditable="True" ItemsSource="{Binding CollectionBindingTwo}"></ComboBox>

【问题讨论】:

    标签: c# wpf xaml binding datagrid


    【解决方案1】:

    DataGridComboBoxColumn 不是可视树的一部分,因此通常的 RelativeSource/ElementName 绑定格式将不起作用。您可以通过定义ElementStyle and 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 命名空间导入。

    【讨论】:

    • 这行得通,谢谢你的回答。我选择了 Styles 选项,因为我不希望此时必须在其他任何地方执行此操作。如果我这样做了,使用你的 BindingProxy 类会更有意义(也谢谢你)。
    【解决方案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>
    

    【讨论】:

    • 感谢您的回答。然而,这并没有奏效,很可能是因为根据 Lee 的回答,VisualTree 的成员身份。 +1,因为这适用于其他情况,我不知道您可以从绑定路径访问 DataContext。
    • @Sergey 谢谢——也请查看这个答案,了解使用x:Reference 的替代方法:stackoverflow.com/a/25021052/1001985
    猜你喜欢
    • 2013-03-30
    • 1970-01-01
    • 2010-12-27
    • 2012-09-28
    • 2013-02-02
    • 2016-01-22
    • 1970-01-01
    • 2023-03-26
    • 2018-05-21
    相关资源
    最近更新 更多