.net 合并主细节数据绑定
我已经从项目中的对象创建了数据源,其中一些对象的成员是其他对象。当我想将一些对象绑定到数据网格时,我也想显示数据网格中成员对象的一些值,但我遇到的示例似乎使用了整个其他数据网格或控件来显示这些成员对象值 如何将这些值合并到一个数据网格中?(最好不创建包装类) 我能用LINQ实现这一点吗 非常感谢你的帮助 谢谢.net 合并主细节数据绑定,.net,vb.net,winforms,data-binding,.net,Vb.net,Winforms,Data Binding,我已经从项目中的对象创建了数据源,其中一些对象的成员是其他对象。当我想将一些对象绑定到数据网格时,我也想显示数据网格中成员对象的一些值,但我遇到的示例似乎使用了整个其他数据网格或控件来显示这些成员对象值 如何将这些值合并到一个数据网格中?(最好不创建包装类) 我能用LINQ实现这一点吗 非常感谢你的帮助 谢谢 p.S.C#或VB示例就可以了。在WinForms中没有干净的方法可以做到这一点。您有几个选项,从最简单到最难: LINQ (这里特别是匿名类型) 您可以这样做: dataGridView
p.S.C#或VB示例就可以了。在WinForms中没有干净的方法可以做到这一点。您有几个选项,从最简单到最难: LINQ (这里特别是匿名类型) 您可以这样做:
dataGridView.DataSource = from x in dataSource
select new
{
Property = x.Property,
SubProperty = x.ObjectProperty.SubProperty // etc.
};
这是迄今为止最简单的方法,但也是单向绑定;无法使用此机制更新数据。这也不会为网格提供设计时支持,因为在设计时无法发现属性名称
包装类
我想这是你熟悉的。创建一个类,该类封装实际的数据绑定类,传递属性并将“子属性”带到类级别。例如:
public string SubProperty
{
get { return yourObject.ObjectProperty.SubProperty; }
set { yourObject.ObjectProperty.SubProperty = value; }
}
这将为网格提供设计时支持(假设使用BindingSource
组件并为此对象正确设置对象数据源),并允许双向绑定。但是,它确实要求您滚动一个包装类并创建要绑定到的每个属性
自定义类型描述符
这是最困难的,但也是最灵活、最快和最干净的(从外部API的角度来看)。在这篇文章中,我不会详细介绍如何做到这一点,但是有一些文章是关于这一点的。我想在自定义类型描述符上链接到MSDN页面,但这有点令人生畏,超出了您尝试的范围
简而言之,您可以创建一个自定义TypeDescriptor类,该类提供PropertyDescriptor实例的列表。这些允许您完全控制绑定体验,而不是依赖反射(在上述两种情况中都是这样)。但是,这是一个非常多的代码,所以在开始之前,您需要确定这是否是您真正想要做的
是对
TypeDescriptor
类及其功能的非常好的介绍。这里您感兴趣的是PropertyDescriptorCollection
。您只需要为每个要与之交互的属性(包括嵌套属性)返回一个PropertyDescriptor
。我最近遇到了同样的问题,并使用上面建议的第三种方法解决了它。下面的DeepBindingList与常规BindingList类似,但有两个增强功能:
1) 它遍历每个属性的子属性,并将它们全部作为可绑定属性公开
2) 它增加了对排序的支持
用任何你喜欢的方式,我希望它有用
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
namespace DeepBindingList
{
/// Extends the BindingList to provide sorting and deep property
/// binding (e.g. Address.Street).
public class DeepBindingList<T> : BindingList<T>, ITypedList
{
//-----------------------------------------------------------------------
#region ** IBindingList overrides (to provide sorting)
PropertyDescriptor _sort;
ListSortDirection _direction;
protected override bool IsSortedCore
{
get { return _sort != null; }
}
protected override void RemoveSortCore()
{
_sort = null;
}
protected override ListSortDirection SortDirectionCore
{
get { return _direction; }
}
protected override PropertyDescriptor SortPropertyCore
{
get { return _sort; }
}
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override void ApplySortCore(PropertyDescriptor pd, ListSortDirection direction)
{
// get list to sort
var items = this.Items as List<T>;
// apply the sort
if (items != null)
{
var pc = new PropertyComparer<T>(pd, direction);
items.Sort(pc);
}
// save new settings and notify listeners
_sort = pd;
_direction = direction;
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
// PropertyComparer (used to sort the list)
class PropertyComparer<TC> : IComparer<TC>
{
PropertyDescriptor _pd;
ListSortDirection _direction;
public PropertyComparer(PropertyDescriptor pd, ListSortDirection direction)
{
_pd = pd;
_direction = direction;
}
public int Compare(TC x, TC y)
{
try
{
var v1 = _pd.GetValue(x) as IComparable;
var v2 = _pd.GetValue(y) as IComparable;
int cmp =
v1 == null && v2 == null ? 0 :
v1 == null ? +1 :
v2 == null ? -1 :
v1.CompareTo(v2);
return _direction == ListSortDirection.Ascending ? +cmp : -cmp;
}
catch
{
return 0; // comparison failed...
}
}
}
#endregion
//-----------------------------------------------------------------------
#region ** ITypedList (to expose inner properties)
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
var list = new List<PropertyDescriptor>();
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(typeof(T)))
{
AddProperties(pd, null, list);
}
return new PropertyDescriptorCollection(list.ToArray());
}
void AddProperties(PropertyDescriptor pd, PropertyDescriptor parent, List<PropertyDescriptor> list)
{
// add this property
pd = new DeepPropertyDescriptor(pd, parent);
list.Add(pd);
// and subproperties for non-value types
if (!pd.PropertyType.IsValueType && pd.PropertyType != typeof(string))
{
foreach (PropertyDescriptor sub in TypeDescriptor.GetProperties(pd.PropertyType))
{
AddProperties(sub, pd, list);
}
}
}
public string GetListName(PropertyDescriptor[] listAccessors)
{
return null;
}
// property descriptor with support for sub properties (e.g. Address.Street)
class DeepPropertyDescriptor : PropertyDescriptor
{
PropertyDescriptor _pd;
PropertyDescriptor _parentPD;
public DeepPropertyDescriptor(PropertyDescriptor pd, PropertyDescriptor parentPd)
: base(pd.Name, null)
{
_pd = pd;
_parentPD = parentPd;
}
public override string Name
{
get
{
return _parentPD != null
? string.Format("{0}.{1}", _parentPD.Name, _pd.Name)
: _pd.Name;
}
}
public override bool IsReadOnly
{
get { return _pd.IsReadOnly; }
}
public override void ResetValue(object component)
{
_pd.ResetValue(component);
}
public override bool CanResetValue(object component)
{
return _pd.CanResetValue(component);
}
public override bool ShouldSerializeValue(object component)
{
return _pd.ShouldSerializeValue(component);
}
public override Type ComponentType
{
get { return _pd.ComponentType; }
}
public override Type PropertyType
{
get { return _pd.PropertyType; }
}
public override object GetValue(object component)
{
if (_parentPD != null)
{
component = _parentPD.GetValue(component);
}
return _pd.GetValue(component);
}
public override void SetValue(object component, object value)
{
_pd.SetValue(_parentPD.GetValue(component), value);
OnValueChanged(component, EventArgs.Empty);
}
}
#endregion
}
}
使用系统;
使用系统组件模型;
使用System.Collections.Generic;
使用系统文本;
命名空间深度绑定列表
{
///扩展BindingList以提供排序和深度属性
///装订(例如地址、街道)。
公共类DeepBindingList:BindingList,ITypedList
{
//-----------------------------------------------------------------------
#区域**IBindingList覆盖(提供排序)
PropertyDescriptor_排序;
ListSortDirection\u方向;
受保护的覆盖布尔IsSortedCore
{
获取{return\u sort!=null;}
}
受保护的覆盖void RemoveSortCore()
{
_sort=null;
}
受保护的覆盖列表SORTDirection SortDirectionCore
{
获取{return\u direction;}
}
受保护的重写属性描述符SortPropertyCore
{
获取{return\u sort;}
}
受保护的覆盖布尔支持SSortingCore
{
获取{return true;}
}
受保护的覆盖无效ApplySortCore(PropertyDescriptor pd,ListSortDirection方向)
{
//获取要排序的列表
var items=此项。项作为列表;
//套用
如果(项!=null)
{
var pc=新财产比较人(pd,方向);
物品分类(pc);
}
//保存新设置并通知侦听器
_排序=pd;
_方向=方向;
this.OnListChanged(新的ListChangedEventArgs(ListChangedType.Reset,-1));
}
//PropertyComparer(用于对列表进行排序)
类属性比较者:IComparer
{
PropertyDescriptor_pd;
ListSortDirection\u方向;
公共属性比较程序(PropertyDescriptor pd,ListSortDirection)
{
_pd=pd;
_方向=方向;
}
公共整数比较(TC x,TC y)
{
尝试
{
VarV1=_pd.GetValue(x)作为可比较变量;
var v2=_pd.GetValue(y)作为i可比较;
整数cmp=
v1==null&&v2==null?0:
v1==null?+1:
v2==null?-1:
v1.比较(v2);
返回_方向==ListSortDirection.升序?+cmp:-cmp;
}
抓住
{
返回0;//比较失败。。。
}
}
}
#端区
//-----------------------------------------------------------------------
#地区**IType
public override void SetValue(object component, object value)
{
if (_parentPD != null)
{
component = _parentPD.GetValue(component);
}
_pd.SetValue(component, value);
OnValueChanged(component, EventArgs.Empty);
}
private PropertyDescriptorCollection propertyDescriptors;
public void SetItemProperties(IList<string> names)
{
var list = new List<PropertyDescriptor>();
foreach (var name in names)
AddProperty(name, list);
propertyDescriptors = new PropertyDescriptorCollection(list.ToArray());
}
private void AddProperty(string name, List<PropertyDescriptor> list)
{
Type propType = typeof (T);
PropertyDescriptor parent = null;
foreach (var part in name.Split('.'))
{
PropertyDescriptor prop = TypeDescriptor.GetProperties(propType).Cast<PropertyDescriptor>().FirstOrDefault(pd => pd.Name == part);
if (prop == null)
return;
list.Add(new DeepPropertyDescriptor(prop, parent));
propType = prop.PropertyType;
parent = prop;
}
}
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
if (propertyDescriptors != null)
return propertyDescriptors;
public DeepBindingList(IList<T> list)
: base(list)
{
}
public DeepBindingList(IEnumerable<T> list)
{
foreach (var t in list)
{
Add(t);
}
}