【问题标题】:WPF DataGrid - Bind DataContext through custom property in parent UserControlWPF DataGrid - 通过父用户控件中的自定义属性绑定 DataContext
【发布时间】:2015-06-30 08:51:18
【问题描述】:

我正在编写一个包含三个 DataGrid(DG_Top、DG_Center、DG_Bottom)的新控件。

当试图为这个控件设置数据时,什么也没有发生。 ContextProperties(见下文)已填充,但未显示数据。

在 UserControl (XGrid) 中,我创建了一些属性来管理 DataBindings:

    public static readonly DependencyProperty ItemsSource_TopProperty = DependencyProperty.Register("ItemsSource_Top", typeof(IEnumerable), typeof(XGrid));
    public static readonly DependencyProperty ItemsSource_CenterProperty = DependencyProperty.Register("ItemsSource_Center", typeof(IEnumerable), typeof(XGrid));
    public static readonly DependencyProperty ItemsSource_BottomProperty = DependencyProperty.Register("ItemsSource_Bottom", typeof(IEnumerable), typeof(XGrid));
    public static readonly DependencyProperty DataContext_TopProperty = DependencyProperty.Register("DataContext_Top", typeof(object), typeof(XGrid));
    public static readonly DependencyProperty DataContext_CenterProperty = DependencyProperty.Register("DataContext_Center", typeof(object), typeof(XGrid));
    public static readonly DependencyProperty DataContext_BottomProperty = DependencyProperty.Register("DataContext_Bottom", typeof(object), typeof(XGrid));


    public IEnumerable ItemsSource_Top
    {
        get { return (IEnumerable)GetValue(ItemsSource_TopProperty); }
        set
        {
            SetValue(ItemsSource_TopProperty, value);
            OnPropertyChanged();
        }
    }
    public IEnumerable ItemsSource_Center...
    public IEnumerable ItemsSource_Bottom...

    public object DataContext_Top
    {
        get { return (object)GetValue(DataContext_TopProperty); }
        set
        {
            SetValue(DataContext_TopProperty, value);
            OnPropertyChanged();
        }
    }

    public object DataContext_Center...
    public object DataContext_Bottom...

XGrid.xaml 中的绑定如下:

    <UserControl x:Class="WPF.XGrid"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         x:Name="control">
 <StackPanel>
    <DataGrid ItemsSource="{Binding ItemsSource_Top, ElementName=control}"
              DataContext="{Binding DataContext_Top, ElementName=control}"  
...

我使用 XGrid 控件如下(在 xaml 中):

<iw:XGrid x:Name="XG_Test" ItemsSource_Center="{Binding}"  />

在.cs文件中:

DataTable dt = new DataTable();
dt.Columns.Add("TEST");
dt.Rows.Add(new string[] { "" });
XG_Test.DataContext_Center = dt.DefaultView;

谁能告诉我为什么绑定不起作用? 谢谢!


-------编辑 1-------

Visual Studio 输出没有说明任何错误

【问题讨论】:

  • 检查 Visual Studio 的输出选项卡,或者使用像 Snoop 这样的工具来检查绑定的属性。您应该能够以这种方式看到实际的 Binding 错误,并知道真正失败的原因。
  • 但除此之外......您是否设置了三个DataContext_x 属性?您确定要设置的 ItemsSource 在该 DataContext 中吗?因为在您的示例中,您设置的是 ItemsSource_Center 而不是 DataContext_Center,这将默认为 null,因此您的 {Binding} 将不绑定任何内容。
  • @almulo 请参阅编辑 1 我在 .cs 文件中设置 DataContext(编辑 1 正上方)=> XG_Test.DataContext_Center = dt.DefaultView;
  • 好的,我想我知道问题出在哪里了。您的 DataGrid 的 ItemsSource 绑定没有考虑 DataGrid DataContext,而是在 XGrid 控件的 DataContext 中搜索其值。
  • @almulo 是的,你是对的,刚刚测试了它设置XG_Test.DataContext = dt.DefaultView;(显示 DG_Center 中的数据)但是我怎样才能让 DataGrid 使用它自己的上下文?

标签: wpf xaml data-binding datagrid dependency-properties


【解决方案1】:

好的,我想我知道问题出在哪里了。您的 DataGrid 的 ItemsSource 绑定没有考虑 DataGrid DataContext,而是在 XGrid 控件的 DataContext 中搜索其值。

你必须确保你正在使用你想要的 DataContext,做这样的事情:

<iw:XGrid x:Name="XG_Test" 
          ItemsSource_Center="{Binding DataContext_Center.DefaultView,
                                       RelativeSource={RelativeSource Mode=Self}}"  />

但是我猜这有点违背了你想要达到的目的......

编辑:我找到了另一种可以使您的原始绑定按预期工作的方法。它要求您修改 UserControl 的代码隐藏并从那里创建 ItemsSource 绑定,而不是从 XAML 进行。

我将以“顶级”DataGrid 为例。

  • 首先,给 UserControl 中的 DataGrids 命名,然后移除 ItemsSource 绑定:

    <DataGrid x:Name="DataGrid_Top"
              DataContext="{Binding DataContext_Top, ElementName=control}" 
              ... /> 
    
  • 然后,为您的 ItemsSource DependencyProperties 声明一个属性更改回调:

    public static readonly DependencyProperty ItemsSource_TopProperty = 
        DependencyProperty.Register("ItemsSource_Top", typeof(IEnumerable), 
        typeof(XGrid), new PropertyMetadata(null, OnItemsSource_TopPropertyChanged));
    
  • 在该回调中,您将创建绑定,但方式与通常不同...

    private static void OnItemsSource_TopPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var control = sender as XGrid;
        var binding = BindingOperations.GetBindingBase(control, XGrid.ItemsSource_TopProperty);
        DataGrid_Top.SetBinding(DataGrid.ItemsSourceProperty, binding);
    }
    

就是这样...您有点将 Binding 从 DependencyProperty “复制”到 ItemsSource 属性中。

然后您可以将 XAML 再次更改为原始示例,它应该可以工作。

<iw:XGrid x:Name="XG_Test" ItemsSource_Center="{Binding}"  />

【讨论】:

  • 谢谢!这完美!也许我可以找到另一种方法来保持语法流畅,但首先这是我正在寻找的解决方案
  • 很高兴它有帮助:) 稍后我可能会再考虑一下,如果我找到更好的方法会回信
猜你喜欢
  • 2016-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多