带有标题“*"的 DataGridColumn 已存在于 DataGrid 的 Columns 集合中 [英] DataGridColumn with Header '*' already exists in the Columns collection of a DataGrid

查看:29
本文介绍了带有标题“*"的 DataGridColumn 已存在于 DataGrid 的 Columns 集合中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 MVVM 模式的 WPF 应用程序.在我看来,我必须绑定一个 ObservableCollection 才能查看.在那个视图中,我有一个 ListBox 和一个 DataGrid 都绑定到相同的 ObservableCollection 但做不同的事情,比如事件、样式等.

I have a WPF application with MVVM pattern. In one of my view, I have to bind an ObservableCollection to view. In that view, I have one ListBox and one DataGrid both bind to the same ObservableCollection but doing different things like events, style etc..

我一次只需要显示其中一个控件,我所做的是创建了两个用户控件,一个用于 DataGrid,另一个用于 ListBox.我通过在主视图上放置一个 ContentControl(类似于这个 blog.默认视图是DataGrid,当点击一个按钮时显示另一个视图(即ListBox).到目前为止一切正常.

I need only one of these controls displayed at a time and what I did is created two user controls, one for DataGrid and other for ListBox. And I switched between them by placing a ContentControl on the main view(something similar to this blog. The default view is DataGrid and when click on a button the other view is displayed(i.e. ListBox). Up to this are working fine.

要记住的另一件事是,数据网格列是使用以下描述的解决方案动态生成的 链接.因此,当我返回 DataGrid 视图时,在 foreach 语句(请参阅上一个链接的答案)中将列添加到数据网格时会引发错误,例如

One more thing to keep in mind that the Data Grid columns are generated dynamically by using the solution described in the following link. So when I go back to DataGrid view it's throwing an error while adding columns to Data Grid in foreach statement (pls refer the answer of the previous link) like

DataGrid 的 Columns 集合中已经存在标题为 'Ord' 的 DataGridColumn.DataGrid 不能共享列,也不能包含重复的列实例."

"DataGridColumn with Header 'Ord' already exists in the Columns collection of a DataGrid. DataGrids cannot share columns and cannot contain duplicate column instances."

但我确信在将列添加到 DataGrid 之前,它的 Count 属性为零(dataGrid.Columns.Count()).那么 DataGrid 标头属性是如何持久化的呢?有没有办法清除标题值?.

But I'm sure that before adding columns to DataGrid its Count property is zero(dataGrid.Columns.Count()). So how the DataGrid header properties are persisted? Is there any way to clear the header values?.

请推荐...

推荐答案

我正在使用 可绑定列.我的网格使用 CollectionViewSource 作为数据源,我在共享列时遇到了同样的问题.我已经用反射修复了.

I'm using the Bindable Column. My grid uses CollectionViewSource for data source and I had same problem with columns being shared. I've fixed with reflection.

所以在 BindableColumnsPropertyChanged 里面改变你的逻辑,如下所示:

So inside BindableColumnsPropertyChanged change your logic like below:

// Add columns from this source.
                foreach (var column in newColumns)
                    if (column != null)
                    {
                        var dg = (DataGrid)column.GetType().GetProperty("DataGridOwner", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(column, null);
                        dg?.Columns.Clear();
                        dataGrid.Columns.Add(column);
                    }

完整代码:

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

namespace SGRE.WOS.Common.UI
{
    public class DataGridColumnsBehavior
    {
        public static readonly DependencyProperty BindableColumnsProperty = DependencyProperty.RegisterAttached("BindableColumns", typeof(ObservableCollection<DataGridColumn>), typeof(DataGridColumnsBehavior), new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
        /// <summary>Collection to store collection change handlers - to be able to unsubscribe later.</summary>
        private static readonly Dictionary<DataGrid, NotifyCollectionChangedEventHandler> _handlers;

        static DataGridColumnsBehavior()
        {
            _handlers = new Dictionary<DataGrid, NotifyCollectionChangedEventHandler>();
        }
        private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            if (!(source is DataGrid dataGrid)) return;
            if (e.OldValue is ObservableCollection<DataGridColumn> oldColumns)
            {
                // Remove all columns.
                dataGrid.Columns.Clear();

                // Unsubscribe from old collection.
                if (_handlers.TryGetValue(dataGrid, out var h))
                {
                    oldColumns.CollectionChanged -= h;
                    _handlers.Remove(dataGrid);
                }
            }

            var newColumns = e.NewValue as ObservableCollection<DataGridColumn>;
            dataGrid.Columns.Clear();
            if (newColumns != null)
            {
                // Add columns from this source.
                foreach (var column in newColumns)
                    if (column != null)
                    {
                        var dg = (DataGrid)column.GetType().GetProperty("DataGridOwner", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(column, null);
                        dg?.Columns.Clear();
                        dataGrid.Columns.Add(column);
                    }


                // Subscribe to future changes.
                NotifyCollectionChangedEventHandler h = (_, ne) => OnCollectionChanged(ne, dataGrid);
                _handlers[dataGrid] = h;
                newColumns.CollectionChanged += h;
            }
        }

        private static void OnCollectionChanged(NotifyCollectionChangedEventArgs ne, DataGrid dataGrid)
        {
            switch (ne.Action)
            {
                case NotifyCollectionChangedAction.Reset:
                    dataGrid.Columns.Clear();
                    if (ne.NewItems != null && ne.NewItems.Count > 0)
                        foreach (DataGridColumn column in ne.NewItems)
                            dataGrid.Columns.Add(column);
                    break;
                case NotifyCollectionChangedAction.Add:
                    foreach (DataGridColumn column in ne.NewItems)
                        dataGrid.Columns.Add(column);
                    break;
                case NotifyCollectionChangedAction.Move:
                    dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (DataGridColumn column in ne.OldItems)
                        dataGrid.Columns.Remove(column);
                    break;
                case NotifyCollectionChangedAction.Replace:
                    dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
                    break;
            }
        }
        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);
        }
    }
}

这篇关于带有标题“*"的 DataGridColumn 已存在于 DataGrid 的 Columns 集合中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆