c# - 如何将 WPF DataGrid 绑定(bind)到可变数量的列?

标签 c# wpf xaml data-binding datagrid

我的 WPF 应用程序生成的数据集每次可能具有不同的列数。输出中包含对将用于应用格式设置的每一列的描述。输出的简化版本可能类似于:

class Data
{
    IList<ColumnDescription> ColumnDescriptions { get; set; }
    string[][] Rows { get; set; }
}

此类设置为 WPF DataGrid 上的 DataContext,但实际上我以编程方式创建列:

for (int i = 0; i < data.ColumnDescriptions.Count; i++)
{
    dataGrid.Columns.Add(new DataGridTextColumn
    {
        Header = data.ColumnDescriptions[i].Name,
        Binding = new Binding(string.Format("[{0}]", i))
    });
}

有没有办法用 XAML 文件中的数据绑定(bind)替换此代码?

最佳答案

这是 DataGrid 中绑定(bind)列的解决方法。由于 Columns 属性是只读的,就像大家注意到的那样,我创建了一个名为 BindableColumns 的附加属性,每当集合通过 CollectionChanged 事件发生更改时,它就会更新 DataGrid 中的列。

如果我们有这个 DataGridColumn 的集合

public ObservableCollection<DataGridColumn> ColumnCollection
{
    get;
    private set;
}

然后我们可以像这样将 BindableColumns 绑定(bind)到 ColumnCollection

<DataGrid Name="dataGrid"
          local:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}"
          AutoGenerateColumns="False"
          ...>

附加属性 BindableColumns

public class DataGridColumnsBehavior
{
    public static readonly DependencyProperty BindableColumnsProperty =
        DependencyProperty.RegisterAttached("BindableColumns",
                                            typeof(ObservableCollection<DataGridColumn>),
                                            typeof(DataGridColumnsBehavior),
                                            new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
    private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        DataGrid dataGrid = source as DataGrid;
        ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
        dataGrid.Columns.Clear();
        if (columns == null)
        {
            return;
        }
        foreach (DataGridColumn column in columns)
        {
            dataGrid.Columns.Add(column);
        }
        columns.CollectionChanged += (sender, e2) =>
        {
            NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
            if (ne.Action == NotifyCollectionChangedAction.Reset)
            {
                dataGrid.Columns.Clear();
                foreach (DataGridColumn column in ne.NewItems)
                {
                    dataGrid.Columns.Add(column);
                }
            }
            else if (ne.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (DataGridColumn column in ne.NewItems)
                {
                    dataGrid.Columns.Add(column);
                }
            }
            else if (ne.Action == NotifyCollectionChangedAction.Move)
            {
                dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
            }
            else if (ne.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (DataGridColumn column in ne.OldItems)
                {
                    dataGrid.Columns.Remove(column);
                }
            }
            else if (ne.Action == NotifyCollectionChangedAction.Replace)
            {
                dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
            }
        };
    }
    public static void SetBindableColumns(DependencyObject element, ObservableCollection<DataGridColumn> value)
    {
        element.SetValue(BindableColumnsProperty, value);
    }
    public static ObservableCollection<DataGridColumn> GetBindableColumns(DependencyObject element)
    {
        return (ObservableCollection<DataGridColumn>)element.GetValue(BindableColumnsProperty);
    }
}

关于c# - 如何将 WPF DataGrid 绑定(bind)到可变数量的列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/320089/

相关文章:

c# - 在 C# 中使用信号量

c# - 如何在 asp.net 中设置文本框输入类型 ="text"?

c# - 如何在 .Net for Mac 中使用 appSettings

c# - Resharper 无法识别正确的 ViewModel 类型

c++ - 如何在 C++ Metro 应用程序中制作 HTTP POST/GET?

c# - 上传超过 2 GB 的大文件。最好的方法是什么?

c# - 无法访问 Telerik 中的 Sort 属性 :RadComboBox

c# - StackPanel 的一侧有一个按钮,另一侧有其他按钮

c# - Xaml.Controls.TextBox 中字符的文本换行

xaml - Lightswitch - 如何重用现有资源?