WPF DataGrid - 通过父UserControl中的自定义属性绑定DataContext

时间:2015-06-30 08:51:19

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

我正在编写一个包含三个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输出没有说明错误

This is what snoop says for the internal DataGrid (DG_Center)

1 个答案:

答案 0 :(得分: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));
    
  • 在该回调中,您将创建Binding,但采用与常规方式不同的方式...

    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);
    }
    

就是这样......你正在将DependencyProperty中的Binding“复制”到ItemsSource属性中。

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

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