问题描述
我还在试验DynamicObjects。现在我需要一些信息:我试图绑定一个对象从DynamicObject继承到WPF DataGrid(不是Silverlight)。
I'm still experimenting with DynamicObjects. Now I need some information: I'm trying to bind an object inheriting from DynamicObject to a WPF DataGrid (not Silverlight).
如何让DataGrid根据通常在运行时生成的对象的可用公共属性自动创建其列?这是可能的吗?
How do I get the DataGrid to automatically create its columns from the available public properties of the object that are typically generated at runtime? Is that possible actually?
推荐答案
没有统一的方法来查询动态属性,通常期望你提前知道它们中。使用 DynamicObject
,实现者可以覆盖 GetMemberNames
,通常会为您提供属性,但是它真正意味着调试,因为不要求它提供所有属性。否则,如果它是你自己的 DynamicObject
,你只需要编写自己的方法来获得基于你的动态实现的属性。例如 ExpandoObject
可以使用 IDictionary
界面查询所有属性。
There is no uniform way to query dynamic properties, generally it's expected that you know them ahead of time. With DynamicObject
, implementers may override GetMemberNames
and that generally gives you the properties, however it is really meant for debugging because there is no requirement that it provide all properties. Otherwise if it's your own DynamicObject
you just have to write your own method to get the properties based on your dynamic implementation. For example ExpandoObject
lets you query all the properties using the IDictionary
interface.
所以一旦你有办法得到你的属性,你需要告诉DataGrid。不幸的是,使用DataGrid,实现 ICustomTypeDescriptor
来告诉DataGrid你的属性的问题是,DataGrid使用Type而不是实例来获取TypeDescriptors,这是Dynamic对象的一个问题,但是在DynamicObjects集合上实现 ITypedList
会使用非常小的函数,如果你不实现非泛型 IList
接口,它将被删除之前,它检查 ITypeList
。
So once you have a way to get your properties you need to tell the DataGrid. Unfortunately with a DataGrid, the issue with implementing ICustomTypeDescriptor
to tell the DataGrid about your properties is that DataGrid gets the TypeDescriptors using the Type not the instance, which is a problem for Dynamic objects, however implementing ITypedList
on the collection of DynamicObjects will work with the very tiny gotcha of if you don't implement the non-generic IList
interface on your collection, it will be stripped out before it gets to the point where it checks for ITypeList
.
总而言之,使用 ITypedList
和 IList
实现集合。使用 ITypedList
返回null为 GetListName
并且只是实现 GetItemProperties(PropertyDescriptor [] listAccessors) code>;忽略
listAccessors
,并根据列表中最好表示的动态对象实例(很可能只是第一个对象)为每个成员返回PropertyDescriptors的PropertyDescriptorCollection。您必须实现PropertyDescriptor的子类,获取/设置值的一个简单而通用的方法是使用opensource框架
So in summary, Implement a Collection with
ITypedList
and IList
. With ITypedList
return null for GetListName
and just implement GetItemProperties(PropertyDescriptor[] listAccessors)
; Ignore listAccessors
and return a PropertyDescriptorCollection of PropertyDescriptors for each member named based on the best represented Dynamic object instance in your list (most likely just the first object). You do have to implement a subclass of PropertyDescriptor, an easy and general way to the Get/Set value is to use the opensource framework Dynamitey
using System;
using System.ComponentModel;
using Dynamitey;
public class DynamicPropertyDescriptor:PropertyDescriptor
{
public DynamicPropertyDescriptor(string name) : base(name, null)
{
}
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
return Dynamic.InvokeGet(component, Name);
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
Dynamic.InvokeSet(component, Name, value);
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return typeof(object); }
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get
{
return typeof (object);
}
}
}
这篇关于将DynamicObject绑定到具有自动列生成的DataGrid?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!