将 DataGrid.Columns 集合绑定到自定义 WPF UserControl 中的祖先

Bind DataGrid.Columns collection to ancestor in custom WPF UserControl

DI 正在尝试将 DataGrid.Columns 属性 公开给 Ancestor UserControl,就像我使用 answer here 处理项目源一样。似乎没有任何属性可供我以下列方式绑定 DataColumns:

<PagedDataGrid>
    <PagedDataGrid.Columns>
        <DataGridTextColumn Header="Custom Column"/>
    <PagedDataGrid.Columns>
</PagedDataGrid>

这是我目前所拥有的。我是否需要以某种方式在后面的代码中执行此操作?

XAML:

<UserControl x:Class="WpfPagedGrid.PagedDataGrid"
         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" 
         xmlns:local="clr-namespace:WpfPagedGrid" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <WrapPanel><TextBlock>Paging Controls...</TextBlock></WrapPanel>
        <DataGrid Name="dataGrid" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, 
                                AncestorType=local:PagedDataGrid, AncestorLevel=1}, Path=ItemsSource}">
        </DataGrid>
    </Grid>
</UserControl>

C#:

namespace WpfPagedGrid {
    public partial class PagedDataGrid : UserControl {
        public PagedDataGrid() { InitializeComponent(); }

        public IEnumerable ItemsSource {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public static readonly DependencyProperty ItemsSourceProperty = DataGrid.ItemsSourceProperty.AddOwner(typeof(PagedDataGrid));

        //Does not work as there is no DataGrid.Columns property...
        //public ObservableCollection<DataGridColumn> Columns {
            //get { return (ObservableCollection<DataGridColumn>)GetValue(ColumnsProperty); }
            //set { SetValue(ItemsSourceProperty, value); }
        //}

        //public static readonly DependencyProperty ColumnsProperty = DataGrid.CloumnsProperty.AddOwner(typeof(PagedDataGrid));
    }
}

编辑: 为了澄清,我正在尝试在用户控件上指定列并将 DataGrid 绑定到这些列。

由于DataGrid.Columns是只读集合,不能直接绑定。相反,您可以通过通常称为 附加行为 的方式来实现这一点。基本上:

  • 创建一个 class 并附加 属性 类型 ObservableCollection
  • 将此 class 绑定到您在 UserControl 上的集合,并将其附加到 DataGrid
  • 在附加 属性 的 On[Property]Changed 处理程序中,您的发件人将是 DataGrid 实例,传入的集合将是您的列。然后您可以设置 DataGrid 列。

所以在代码中:

<DataGrid Name="dataGrid" ...
    MyColumnHelper.Columns="{Binding RelativeSource={RelativeSource FindAncestor,
    AncestorType=local:PagedDataGrid, AncestorLevel=1}, Path=MyColumns}" />

对于处理程序:

OnMyColumnHelperColumnsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
    DataGrid.Columns.Clear();
    foreach(var column in (IEnumerable)args.NewValue)
    {
        DataGrid.Columns.Add(column);
    }
}

警告 - 上面的代码是为用户控件上的基础集合每次要添加或删除列时创建一个新集合而编写的。虽然您可以使用 ObservableCollection,但您 运行 变得复杂:

  • 你必须在上面的事件处理程序中订阅它的CollectionChanged事件
  • 然后你必须使用弱事件,或者也订阅 DataGrid.Unloaded 事件,这样你就可以取消订阅 CollectionChanged 并防止内存泄漏(这将是一个生命周期的问题您的用户控件比您的数据网格长,或者如果您的数据网格曾经被卸载并重新加载到可视化树中)