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

时间:2014-04-17 15:38:17

标签: c# wpf datagrid

我搜索了这个,但我没有找到这个具体问题的答案(虽然有很多相似的问题)。

我的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属性显示为单元格&#39;值。我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

我使用herehere中的提示达到了这个目标。我在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。唯一的限制是绑定是一种不太难解决的方法。