C#/winforms:如何最好地绑定 propertygrid 和 System.Data.DataRow
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/943621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#/winforms: how to best bind a propertygrid and a System.Data.DataRow
提问by clamp
i have System.Data.DataRows with several fields, most of them just plain types like int, single, string.
我有几个字段的 System.Data.DataRows,其中大多数只是普通类型,如 int、single、string。
what is the best way to make them editable using a propertygrid? it should work automatically no matter what kind of fields the datarow has, but it should not display all of them. i want to provide a list of properties that should be hidden.
使用属性网格使它们可编辑的最佳方法是什么?无论数据行有什么类型的字段,它都应该自动工作,但它不应该显示所有字段。我想提供一个应该隐藏的属性列表。
since the DataTable is autogenerated i cannot add custom attributes like [Browsable(false)]
由于 DataTable 是自动生成的,因此我无法添加自定义属性,例如 [Browsable(false)]
thanks a lot!
多谢!
采纳答案by Marc Gravell
Edited to handle filtering; much tricker: in addition to getting the DataRowView
, we need to provide a custom component that pretends (via pass-thru PropetyDescriptor
s) to be the DataRowView
(which is itself pretending to be the DataRow
) - and filter out the properties that we don't want.
编辑处理过滤;诡计多端:除了获取 之外DataRowView
,我们还需要提供一个自定义组件,该组件假装(通过传递PropetyDescriptor
)为DataRowView
(它本身假装为DataRow
) - 并过滤掉我们不想要的属性。
Very interesting problem ;-p Easier to solve in classic classes, but the below works for DataRow
;-p
非常有趣的问题 ;-p 在经典课程中更容易解决,但以下适用于DataRow
;-p
Note that you could do other things in this area to make some of the properties non-editable (IsReadOnly
), or have a different caption (DisplayName
), or category (Category
) - by overriding other members in RowWrapperDescriptor
.
注意,你可以做其他的事情在这方面做一些属性不可编辑的(的IsReadOnly
),或有不同的标题(DisplayName
),或类别(Category
) -通过重写其他成员RowWrapperDescriptor
。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
static class program
{
[STAThread]
static void Main()
{
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Foo", typeof(int));
table.Columns.Add("Bar", typeof(string));
table.Columns.Add("Audit", typeof(DateTime));
table.Rows.Add(1, 14, "abc", DateTime.MinValue);
DataRow row = table.Rows.Add(2,13,"def", DateTime.MinValue);
table.Rows.Add(3, 24, "ghi", DateTime.MinValue);
RowWrapper wrapper = new RowWrapper(row);
wrapper.Exclude.Add("ID");
wrapper.Exclude.Add("Bar");
Application.EnableVisualStyles();
Application.Run(new Form {Controls = {
new PropertyGrid { Dock = DockStyle.Fill,
SelectedObject = wrapper}}});
}
}
[TypeConverter(typeof(RowWrapper.RowWrapperConverter))]
class RowWrapper
{
private readonly List<string> exclude = new List<string>();
public List<string> Exclude { get { return exclude; } }
private readonly DataRowView rowView;
public RowWrapper(DataRow row)
{
DataView view = new DataView(row.Table);
foreach (DataRowView tmp in view)
{
if (tmp.Row == row)
{
rowView = tmp;
break;
}
}
}
static DataRowView GetRowView(object component)
{
return ((RowWrapper)component).rowView;
}
class RowWrapperConverter : TypeConverter
{
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
public override PropertyDescriptorCollection GetProperties(
ITypeDescriptorContext context, object value, Attribute[] attributes)
{
RowWrapper rw = (RowWrapper)value;
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(
GetRowView(value), attributes);
List<PropertyDescriptor> result = new List<PropertyDescriptor>(props.Count);
foreach (PropertyDescriptor prop in props)
{
if (rw.Exclude.Contains(prop.Name)) continue;
result.Add(new RowWrapperDescriptor(prop));
}
return new PropertyDescriptorCollection(result.ToArray());
}
}
class RowWrapperDescriptor : PropertyDescriptor
{
static Attribute[] GetAttribs(AttributeCollection value)
{
if (value == null) return null;
Attribute[] result = new Attribute[value.Count];
value.CopyTo(result, 0);
return result;
}
readonly PropertyDescriptor innerProp;
public RowWrapperDescriptor(PropertyDescriptor innerProperty)
: base(
innerProperty.Name, GetAttribs(innerProperty.Attributes))
{
this.innerProp = innerProperty;
}
public override bool ShouldSerializeValue(object component)
{
return innerProp.ShouldSerializeValue(GetRowView(component));
}
public override void ResetValue(object component)
{
innerProp.ResetValue(GetRowView(component));
}
public override bool CanResetValue(object component)
{
return innerProp.CanResetValue(GetRowView(component));
}
public override void SetValue(object component, object value)
{
innerProp.SetValue(GetRowView(component), value);
}
public override object GetValue(object component)
{
return innerProp.GetValue(GetRowView(component));
}
public override Type PropertyType
{
get { return innerProp.PropertyType; }
}
public override Type ComponentType
{
get { return typeof(RowWrapper); }
}
public override bool IsReadOnly
{
get { return innerProp.IsReadOnly; }
}
}
}