DataGrid 的 WPF 动态列和值 [英] WPF dynamic columns and values for DataGrid

查看:40
本文介绍了DataGrid 的 WPF 动态列和值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个 DataGrid.一个列出项目列表,另一个保存规范.

I have two DataGrids. One list the list of items and the other holds the specification.

如果我在第一个网格中选择监视器,则第二个网格应显示其自己的规格.如果我选择 CPU,它应该在另一个网格上显示其规格.

If i select Monitor in the 1st grid , The second grid should show its own specifications . and if i select CPU it should display its specifications on the other gird.

我正在寻找一个好的解决方案来做到这一点.截至目前,我打算创建一个具有 string 属性和 DataTable 属性的模型,以便我可以创建将动态表绑定到第二个网格.但我正在寻找诸如动态属性或更好的解决方案之类的东西.

I looking for a good solution to do this . As of now im planing to create a model with a property of string and a DataTable so i can create a bind the dynamic table to second grid . But im looking for something like dynamic property or some better Solution .

谢谢

推荐答案

对于这种情况,我使用我的 GenericRow 和 GenericTable 类:

For such a case I use my GenericRow and GenericTable classes:

public class GenericRow : CustomTypeDescriptor, INotifyPropertyChanged
{

    #region Private Fields
    List<PropertyDescriptor> _property_list = new List<PropertyDescriptor>();
    #endregion

    #region INotifyPropertyChange Implementation

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChange Implementation

    #region Public Methods

    public void SetPropertyValue<T>(string propertyName, T propertyValue)
    {
        var properties = this.GetProperties()
                                .Cast<PropertyDescriptor>()
                                .Where(prop => prop.Name.Equals(propertyName));

        if (properties == null || properties.Count() != 1)
        {
            throw new Exception("The property doesn't exist.");
        }

        var property = properties.First();
        property.SetValue(this, propertyValue);

        OnPropertyChanged(propertyName);
    }

    public T GetPropertyValue<T>(string propertyName)
    {
        var properties = this.GetProperties()
                            .Cast<PropertyDescriptor>()
                            .Where(prop => prop.Name.Equals(propertyName));

        if (properties == null || properties.Count() != 1)
        {
            throw new Exception("The property doesn't exist.");
        }

        var property = properties.First();
        return (T)property.GetValue(this);
    }

    public void AddProperty<T, U>(string propertyName) where U : GenericRow
    {
        var customProperty =
                new CustomPropertyDescriptor<T>(
                                        propertyName,
                                        typeof(U));

        _property_list.Add(customProperty);
    }

    #endregion

    #region Overriden Methods

    public override PropertyDescriptorCollection GetProperties()
    {
        var properties = base.GetProperties();
        return new PropertyDescriptorCollection(
                            properties.Cast<PropertyDescriptor>()
                                      .Concat(_property_list).ToArray());
    }

    #endregion

}

和:

 public class GenericTable
{

    private string tableName = "";
    public string TableName
    {
        get { return tableName; }
        set { tableName = value; }
    }

    private ObservableCollection<DataGridColumn> columnCollection;
    public ObservableCollection<DataGridColumn> ColumnCollection
    {
        get { return columnCollection; }
        private set { columnCollection = value; }
    }

    private ObservableCollection<GenericRow> genericRowCollection;
    public ObservableCollection<GenericRow> GenericRowCollection
    {
        get { return genericRowCollection; }
        set { genericRowCollection = value; }
    }




    public GenericTable(string tableName)
    {
        this.TableName = tableName;
        ColumnCollection = new ObservableCollection<DataGridColumn>();
        GenericRowCollection = new ObservableCollection<GenericRow>(); 
    }

    /// <summary>
    /// ColumnName is also binding property name
    /// </summary>
    /// <param name="columnName"></param>
    public void AddColumn(string columnName)
    {
        DataGridTextColumn column = new DataGridTextColumn();
        column.Header = columnName;
        column.Binding = new Binding(columnName);
        ColumnCollection.Add(column);
    }



    public override string ToString()
    {
        return TableName; 
    }


}

您可以使用这两个类来创建动态行和列.使用 GenericRow 类,您可以生成具有所需属性名称的行,并且可以为探测器绑定的列使用相同的属性名称.

You can use these two classes to create dynamic rows and columns. Using GenericRow class, you can generate row with desired property name and you can use the same property name for the columns for prober binding.

对于 XAML 端:

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

最后是 DataGridColumsBehaior :

and finally DataGridColumsBehaior :

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

最后,您可以创建 GenericRows 并将它们添加到 GenericTable 中.它就像一个小的视图模型.在 XAML 端,不要忘记将 rowscollection 绑定为 DataGrid 的 itemsource.

In the end, you can create GenericRows and add them into GenericTable. It is like a small viewmodel. In XAML side, dont forget to bind rowscollection as itemsource of the DataGrid.

这篇关于DataGrid 的 WPF 动态列和值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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