繁体   English   中英

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

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

我进行了搜索,但是没有找到这个特定问题的答案(尽管有很多类似的问题)。

我的ViewModel中有一个Column类,如下所示:

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

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

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

我想将后一类的Columns属性绑定到视图中的DataGrid列。 对于每个Column实例,我想将Header属性显示为列的标题,并将其Data属性显示为单元格的值。 我怎样才能做到这一点?

我使用这里这里的想法达到了这个目标。 我在VM中实现了三个类: TableRowRowPropertyDescriptor 这是代码:

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
}

然后,可以轻松地将Table的列传递给此类来创建Table Table可以在视图中正确显示。 唯一的限制是绑定是一种很难解决的方法。

暂无
暂无

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

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