You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF自定义带标题DataGrid用户控件的列绑定问题

解决WPF自定义DataGrid UserControl的Columns属性绑定问题

你的问题核心是只定义了Columns依赖属性,但没有将其与内部DataGrid的Columns集合建立同步关联,同时忽略了集合变更的事件监听。以下是具体解决步骤:


1. 修改UserControl的XAML,给内部DataGrid命名

首先在XAML里给内部DataGrid加上x:Name,方便后台代码访问:

<UserControl x:Class="SupervisoreIB.UI.CustomControls.DataGridWithHeader"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <Border Grid.Row="0">
            <Label Content="test" />
        </Border>
        <Border Grid.Row="1">
            <!-- 给内部DataGrid命名 -->
            <DataGrid x:Name="InnerDataGrid" />
        </Border>
    </Grid>
</UserControl>

2. 完善后台依赖属性与集合同步逻辑

需要处理以下几点:

  • 初始化默认的ObservableCollection<DataGridColumn>,避免null值
  • 监听集合的CollectionChanged事件,同步列的添加/移除操作
  • 在依赖属性变更时,切换旧/新集合的事件监听,并同步已有列

完整后台代码:

using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;

namespace SupervisoreIB.UI.CustomControls
{
    public partial class DataGridWithHeader : UserControl
    {
        public DataGridWithHeader()
        {
            InitializeComponent();
            // 初始化默认集合
            Columns = new ObservableCollection<DataGridColumn>();
        }

        public ObservableCollection<DataGridColumn> Columns
        {
            get { return (ObservableCollection<DataGridColumn>)GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }

        public static readonly DependencyProperty ColumnsProperty =
            DependencyProperty.Register("Columns", typeof(ObservableCollection<DataGridColumn>), typeof(DataGridWithHeader), 
                new PropertyMetadata(null, OnColumnsChanged));

        private static void OnColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (DataGridWithHeader)d;
            var oldColumns = e.OldValue as ObservableCollection<DataGridColumn>;
            var newColumns = e.NewValue as ObservableCollection<DataGridColumn>;

            // 移除旧集合的事件监听
            if (oldColumns != null)
            {
                oldColumns.CollectionChanged -= control.Columns_CollectionChanged;
            }

            // 绑定新集合的事件监听,并同步已有列
            if (newColumns != null)
            {
                newColumns.CollectionChanged += control.Columns_CollectionChanged;
                control.SyncColumns(newColumns);
            }
            else
            {
                // 如果新集合为null,清空内部DataGrid的列
                control.InnerDataGrid.Columns.Clear();
            }
        }

        private void Columns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            var columns = sender as ObservableCollection<DataGridColumn>;
            if (columns == null) return;

            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    // 添加新列到内部DataGrid
                    foreach (DataGridColumn column in e.NewItems)
                    {
                        InnerDataGrid.Columns.Add(column);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    // 从内部DataGrid移除列
                    foreach (DataGridColumn column in e.OldItems)
                    {
                        InnerDataGrid.Columns.Remove(column);
                    }
                    break;
                case NotifyCollectionChangedAction.Reset:
                    // 重置时清空并重新添加所有列
                    InnerDataGrid.Columns.Clear();
                    SyncColumns(columns);
                    break;
            }
        }

        // 同步集合中所有列到内部DataGrid
        private void SyncColumns(ObservableCollection<DataGridColumn> columns)
        {
            InnerDataGrid.Columns.Clear();
            foreach (var column in columns)
            {
                InnerDataGrid.Columns.Add(column);
            }
        }
    }
}

3. 验证使用方式

现在你可以按照预期的方式使用自定义控件:

<uc:DataGridWithHeader Grid.Row="1" Grid.Column="0" Margin="10">
    <uc:DataGridWithHeader.Columns>
        <DataGridTextColumn Header="COL1" />
        <DataGridTextColumn Header="COL2" />
        <DataGridTextColumn Header="COL3" />
    </uc:DataGridWithHeader.Columns>
</uc:DataGridWithHeader>

关键说明

  • DataGrid的Columns属性是DataGridColumnCollection类型,不是ObservableCollection,所以不能直接赋值,必须通过Add/Remove方法同步
  • 必须监听ObservableCollection的CollectionChanged事件,才能响应外部动态添加/移除列的操作
  • 初始化默认集合可以避免XAML使用时出现空引用问题

内容的提问来源于stack exchange,提问作者andboz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 00:26:04