简体   繁体   English

如何将DataGrid绑定到WPF中的列列表

[英]How to bind a DataGrid to a list of columns in WPF

I searched this, but I didn't find the answer to this specific question (although there are many similar ones). 我进行了搜索,但是没有找到这个特定问题的答案(尽管有很多类似的问题)。

I have a Column class in my ViewModel like this: 我的ViewModel中有一个Column类,如下所示:

public class Column
{
    public string Header { get; set; }
    public ObservableCollection<double> Data { get; private set; }

    public DummyColumn()
    {
        Data = new ObservableCollection<double>();
    }
}

In MyViewModel class itself, I have Columns property: MyViewModel类本身中,我具有Columns属性:

public class MyViewModel
{
    public ObservableCollection<Column> { get; private set; }

    public MyViewModel()
    {
        Columns = new ObservableCollection<DummyColumn>();

        var c1 = new DummyColumn() { Header = "A" };
        c1.Data.Add(5);
        c1.Data.Add(6);
        Columns.Add(c1);

        var c2 = new DummyColumn() { Header = "B" };
        c2.Data.Add(51);
        c2.Data.Add(61);
        Columns.Add(c2);
    }
}

I want to bind the Columns property of the latter class to the columns of a DataGrid in view. 我想将后一类的Columns属性绑定到视图中的DataGrid列。 For each Column instance, I want to show the Header property as the column's header and its Data property as cells' values. 对于每个Column实例,我想将Header属性显示为列的标题,并将其Data属性显示为单元格的值。 How can I do that? 我怎样才能做到这一点?

I reached this goal using ideas from here and here . 我使用这里这里的想法达到了这个目标。 I implemented three classes: Table , Row and RowPropertyDescriptor in my VM. 我在VM中实现了三个类: TableRowRowPropertyDescriptor Here is the code: 这是代码:

class RowPropertyDescriptor : PropertyDescriptor
{
    private int index;

    public RowPropertyDescriptor(string name, int index)
        : base(name, null)
    {
        this.index = index;
    }

    #region PropertyDescriptor

    public override string DisplayName { get { return Name; } }

    public override Type ComponentType { get { return typeof(double); } }

    public override bool IsReadOnly { get { return false; } }

    public override Type PropertyType { get { return typeof(double); } }

    public override object GetValue(object component)
    {
        return ((Row)component)[index];
    }

    public override void SetValue(object component, object value)
    {
        ((Row)component)[index] = (double)value;
    }

    public override bool CanResetValue(object component)
    {
        return false;
    }

    public override void ResetValue(object component)
    {

    }

    public override bool ShouldSerializeValue(object component)
    {
        return false;
    }

    #endregion
}

class Row : DynamicObject
{
    private Table table;
    private int row;

    public Row(Table namedArraysView, int row)
    {
        this.table = namedArraysView;
        this.row = row;
    }

    public double this[int col]
    {
        get { return table.RawData[col].Data[row]; }
        set { table.RawData[col].Data[row] = value; }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        int idx;
        bool found = table.PropertiesIndex.TryGetValue(binder.Name, out idx);
        if (found)
        {
            try
            {
                this[idx] = Convert.ToDouble(value);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        return base.TrySetMember(binder, value);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        int idx;
        bool found = table.PropertiesIndex.TryGetValue(binder.Name, out idx);
        if (found)
        {
            result = this[idx];
            return true;
        }

        return base.TryGetMember(binder, out result);
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return table.PropertyNames;
    }
}

class Table : BindingList<Row>, ITypedList
{
    public ObservableCollection<INamedArray> RawData { get; private set; }
    internal List<string> PropertyNames { get; private set; }
    internal Dictionary<string, int> PropertiesIndex { get; private set; }

    public Table(ObservableCollection<INamedArray> headeredArrays)
    {
        bind(headeredArrays);

        headeredArrays.CollectionChanged += (object sender, NotifyCollectionChangedEventArgs e) => { bind(headeredArrays); };
    }

    private void bind(ObservableCollection<INamedArray> headeredArrays)
    {
        Clear();

        if (headeredArrays == null)
        {
            RawData = null;
            PropertyNames = null;
            PropertiesIndex = null;
            return;
        }

        RawData = headeredArrays;
        PropertyNames = RawData.Select(d => d.Name).ToList();

        PropertiesIndex = new Dictionary<string, int>();
        for (int i = 0; i < RawData.Count; i++)
            PropertiesIndex.Add(RawData[i].Name, i);

        int nRows = headeredArrays[0].Data.Count;
        for (int i = 0; i < nRows; i++)
            Add(new Row(this, i));
    }

    #region ITypedList

    public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
    {
        var dynamicDescriptors = new List<PropertyDescriptor>();
        if (this[0].GetDynamicMemberNames() == null) return new PropertyDescriptorCollection(new PropertyDescriptor[] { });
        var memberNames = this[0].GetDynamicMemberNames().ToArray();

        for (int i = 0; i < memberNames.Length; i++)
            dynamicDescriptors.Add(new RowPropertyDescriptor(memberNames[i], i));

        return new PropertyDescriptorCollection(dynamicDescriptors.ToArray());
    }

    public string GetListName(PropertyDescriptor[] listAccessors)
    {
        return null;
    }

    #endregion
}

Then, one can easily create a Table with passing his/her columns to this class. 然后,可以轻松地将Table的列传递给此类来创建Table This Table can be visualised correctly in view. Table可以在视图中正确显示。 The only limitation is that binding is one way which is not very hard to work around. 唯一的限制是绑定是一种很难解决的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM