复杂数据绑定:实现IBindingList和ITypedList的集合






4.60/5 (22投票s)
2003年3月27日
2分钟阅读

197188

3802
复杂数据绑定:
引言
数据绑定可能很棘手 - 尤其是当您无法使用 System.Data
对象时。我试图使用数据绑定的所有功能来向您展示它们。它很小,但要做到这一点需要很长时间。
该示例展示了一个自定义集合,其中包含具有属性的对象,其中一些属性又是集合,其中包含对象 - 即分层数据。也许某些属性无法直接编辑,因为网格不够智能 - 例如 SqlTypes
。
问题
我们有一个需要放入 Windows DataGrid
的对象集合。它们可能具有也可能没有作为集合的属性。
解决方案
我们需要创建以下对象
- 一个实现
ITypedList
和IBindingList
的类(您的集合) - 一个作为您数据的类(大量属性等)
- 一个实现
IComparer
的类(用于排序) - 一个实现
PropertyDescriptor
的类(用于使用非网格兼容类型,例如SqlTypes
) - 一个实现
Attribute
的类(以便我们知道集合中有什么)
对于那些尝试过但没有成功的人,我将讨论几个出现的问题。
ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
这是项目中界面最棘手的方法。问题与 listAccessors
有关。如果参数不是 null
,则应该只处理最后一个。我不得不反编译 System.Data.DataView.ITypedList.GetItemProperties
才能找到它。然后我需要检测我们的自定义集合并返回基础数据的属性。
SqlPropertyDescriptor : PropertyDescriptor
这个虽然实现起来很简单,但在调用 GetItemProperties
时有点棘手,并且我们希望使用此 PropertyDesciptor
而不是默认值,我们需要在集合中替换它。我写了这个方法来做到这一点
protected PropertyDescriptorCollection
GetPropertyDescriptorCollection( ArrayList properties )
{
if ( properties == null || properties.Count == 0 )
return new PropertyDescriptorCollection(null);
ArrayList output = new ArrayList();
foreach ( PropertyDescriptor p in properties )
{
if ( p.Attributes.Matches(new Attribute[]
{new BindableAttribute(false)}) ) continue;
if ( p.PropertyType.Namespace == "System.Data.SqlTypes" )
{
// create the base type property descriptor
output.Add(SqlPropertyDescriptor.
GetProperty( p.Name, p.PropertyType ) );
}
else
{
output.Add(p);
}
}
return new PropertyDescriptorCollection((PropertyDescriptor[])
output.ToArray(typeof(PropertyDescriptor)));
}
在那之后,一切都很顺利。
PropertyDescriptor
的 SetValue
和 GetValue
提供了编辑 SqlTypes
(如 SqlDateTime
)的方法。在检测到数据类型的命名空间后,我使用 SqlPropertDescriptor
,它实现了 GetValue()
和 SetValue()
。这些方法试图为自己解决所有问题
public override void SetValue(object component,object value)
{
try
{
PropertyInfo pi = component.GetType().GetProperty(this.Name);
Object o;
if ( value == DBNull.Value )
{
o = component.GetType().GetField("Null",
BindingFlags.Static | BindingFlags.Public |
BindingFlags.GetField).GetValue(component);
}
else
{
o = pi.PropertyType.GetConstructor(new Type[]
{BaseType}).Invoke(new Object[]{value});
}
pi.SetValue(component,o, null);
}
catch(Exception ex)
{
Debug.WriteLine(ex);
}
}
public override object GetValue(object component)
{
try
{
object Property = component.GetType().GetProperty
(this.Name).GetValue(component,null);
// handle nulls
if ( (bool)Property.GetType().GetProperty
("IsNull").GetValue(Property,null) )
return DBNull.Value;
object Value = Property.GetType().GetProperty
("Value").GetValue(Property,null);
return Value;
}
catch(Exception ex)
{
Debug.WriteLine(ex);
}
return null;
}
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。