【发布时间】:2011-02-12 15:03:51
【问题描述】:
我正在使用 PropertyDescriptor 和 ICustomTypeDescriptor (still) 尝试将 WPF DataGrid 绑定到一个对象,该对象的数据存储在字典中。
如果您向 WPF DataGrid 传递一个 Dictionary 对象列表,它将根据字典的公共属性(比较器、计数、键和值)自动生成列,因此我的 Person 是 Dictionary 的子类并实现 ICustomTypeDescriptor。
ICustomTypeDescriptor 定义了一个 GetProperties 方法,该方法返回一个 PropertyDescriptorCollection。
PropertyDescriptor 是抽象的,因此您必须对其进行子类化,我想我应该有一个构造函数,它采用 Func 和一个 Action 参数来委托获取和设置字典中的值。
然后我为字典中的每个键创建一个 PersonPropertyDescriptor,如下所示:
foreach (string s in this.Keys)
{
var descriptor = new PersonPropertyDescriptor(
s,
new Func<object>(() => { return this[s]; }),
new Action<object>(o => { this[s] = o; }));
propList.Add(descriptor);
}
问题在于,每个属性都有自己的 Func 和 Action,但它们都共享外部变量 s,因此尽管 DataGrid 自动为“ID”、“FirstName”、“LastName”、“ Age", "Gender" 他们都得到并设置了 "Gender",这是 foreach 循环中 s 的最终静止值。
如何确保每个委托都使用所需的字典键,即实例化 Func/Action 时 s 的值?
非常感谢。
这是我剩下的想法,我只是在这里试验这些不是“真正的”类......
// DataGrid binds to a People instance
public class People : List<Person>
{
public People()
{
this.Add(new Person());
}
}
public class Person : Dictionary<string, object>, ICustomTypeDescriptor
{
private static PropertyDescriptorCollection descriptors;
public Person()
{
this["ID"] = "201203";
this["FirstName"] = "Bud";
this["LastName"] = "Tree";
this["Age"] = 99;
this["Gender"] = "M";
}
//... other ICustomTypeDescriptor members...
public PropertyDescriptorCollection GetProperties()
{
if (descriptors == null)
{
var propList = new List<PropertyDescriptor>();
foreach (string s in this.Keys)
{
var descriptor = new PersonPropertyDescriptor(
s,
new Func<object>(() => { return this[s]; }),
new Action<object>(o => { this[s] = o; }));
propList.Add(descriptor);
}
descriptors = new PropertyDescriptorCollection(propList.ToArray());
}
return descriptors;
}
//... other other ICustomTypeDescriptor members...
}
public class PersonPropertyDescriptor : PropertyDescriptor
{
private Func<object> getFunc;
private Action<object> setAction;
public PersonPropertyDescriptor(string name, Func<object> getFunc, Action<object> setAction)
: base(name, null)
{
this.getFunc = getFunc;
this.setAction = setAction;
}
// other ... PropertyDescriptor members...
public override object GetValue(object component)
{
return getFunc();
}
public override void SetValue(object component, object value)
{
setAction(value);
}
}
【问题讨论】:
标签: c# lambda wpfdatagrid icustomtypedescriptor