我搜索了这个,但我没有找到这个具体问题的答案(虽然有很多相似的问题)。
我的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;值。我怎么能这样做?
答案 0 :(得分:1)
我使用here和here中的提示达到了这个目标。我在VM中实现了三个类:Table
,Row
和RowPropertyDescriptor
。这是代码:
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
。唯一的限制是绑定是一种不太难解决的方法。