簡體   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