PropertyDescriptor と ICustomTypeDescriptor (まだ) で遊んでいて、データが辞書に格納されているオブジェクトに WPF DataGrid をバインドしようとしています。
WPF DataGrid に Dictionary オブジェクトのリストを渡すと、辞書のパブリック プロパティ (Comparer、Count、Keys、および Values) に基づいて列が自動生成されるため、私の Person は Dictionary をサブクラス化し、ICustomTypeDescriptor を実装します。
ICustomTypeDescriptor は、PropertyDescriptorCollection を返す GetProperties メソッドを定義します。
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」の列を自動生成しますが、それらはすべて取得され、foreach ループ内の s の最終値である「Gender」に対して設定します。
各デリゲートが目的のディクショナリ キー、つまり 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);
}
}