有没有办法在 PropertyGrid 中显示静态属性?
Is there a way to display static properties in a PropertyGrid?
我有一个 PropertyGrid
显示对象的所有实例属性。有没有办法在同一个或单独的 PropertyGrid
中也显示对象所属的 class 的静态属性?或者,是否有另一个 Forms 控件允许我执行此操作?
类型描述符负责提供要在 PropertyGrid
中显示的属性列表。
要自定义属性列表,您需要使用以下任一选项为您的 class/object 提供自定义类型描述:
- 你的class可以实现
ICustomTypeDescriptor
- 您的 class 可以派生自
CustomTypeDescriptor
- 您可以通过从上方 interface/class 驱动并使用
TypeDescriptionProvider
为您的 class 或对象实例注册它来为您的 class 创建一个新的类型描述符
- 您可以通过从
CustomTypeDescriptor
派生来创建包装器对象,仅用于 PropertyGrid
.
例子
在这个例子中,我实现了最后一个选项。我假设您要保持主要 class 不变,只是为了在 PropertyGrid
中显示,我创建了一个自定义包装对象,它为 属性 网格提供了一个属性列表,包括静态属性。
假设您有这样一个 class:
public class MyClass
{
public string InstanceProperty { get; set; }
public static string StaticProperty { get; set; } = "Test";
}
并且您想在 PropertyGrid
中显示它的属性。
那么通常你首先需要的是一个新的 属性 描述符:
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
public class StaticPropertyDescriptor : PropertyDescriptor
{
PropertyInfo p;
Type owenrType;
public StaticPropertyDescriptor(PropertyInfo pi, Type owenrType)
: base(pi.Name,
pi.GetCustomAttributes().Cast<Attribute>().ToArray())
{
p = pi;
this.owenrType = owenrType;
}
public override bool CanResetValue(object c) => false;
public override object GetValue(object c) => p.GetValue(null);
public override void ResetValue(object c) { }
public override void SetValue(object c, object v) => p.SetValue(null, v);
public override bool ShouldSerializeValue(object c) => false;
public override Type ComponentType { get { return owenrType; } }
public override bool IsReadOnly { get { return !p.CanWrite; } }
public override Type PropertyType { get { return p.PropertyType; } }
}
然后你可以使用我上面提到的任何一个选项。例如,在这里我创建了一个包装器类型描述符以不触及原始 class:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
public class CustomObjectWrapper : CustomTypeDescriptor
{
public object WrappedObject { get; private set; }
private IEnumerable<PropertyDescriptor> staticProperties;
public CustomObjectWrapper(object o)
: base(TypeDescriptor.GetProvider(o).GetTypeDescriptor(o))
{
WrappedObject = o;
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var instanceProperties = base.GetProperties(attributes)
.Cast<PropertyDescriptor>();
staticProperties = WrappedObject.GetType()
.GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(p => new StaticPropertyDescriptor(p, WrappedObject.GetType()));
return new PropertyDescriptorCollection(
instanceProperties.Union(staticProperties).ToArray());
}
}
而且用法很简单:
var myClass = new MyClass();
propertyGrid1.SelectedObject = new CustomObjectWrapper (myClass);
我有一个 PropertyGrid
显示对象的所有实例属性。有没有办法在同一个或单独的 PropertyGrid
中也显示对象所属的 class 的静态属性?或者,是否有另一个 Forms 控件允许我执行此操作?
类型描述符负责提供要在 PropertyGrid
中显示的属性列表。
要自定义属性列表,您需要使用以下任一选项为您的 class/object 提供自定义类型描述:
- 你的class可以实现
ICustomTypeDescriptor
- 您的 class 可以派生自
CustomTypeDescriptor
- 您可以通过从上方 interface/class 驱动并使用
TypeDescriptionProvider
为您的 class 或对象实例注册它来为您的 class 创建一个新的类型描述符 - 您可以通过从
CustomTypeDescriptor
派生来创建包装器对象,仅用于PropertyGrid
.
例子
在这个例子中,我实现了最后一个选项。我假设您要保持主要 class 不变,只是为了在 PropertyGrid
中显示,我创建了一个自定义包装对象,它为 属性 网格提供了一个属性列表,包括静态属性。
假设您有这样一个 class:
public class MyClass
{
public string InstanceProperty { get; set; }
public static string StaticProperty { get; set; } = "Test";
}
并且您想在 PropertyGrid
中显示它的属性。
那么通常你首先需要的是一个新的 属性 描述符:
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
public class StaticPropertyDescriptor : PropertyDescriptor
{
PropertyInfo p;
Type owenrType;
public StaticPropertyDescriptor(PropertyInfo pi, Type owenrType)
: base(pi.Name,
pi.GetCustomAttributes().Cast<Attribute>().ToArray())
{
p = pi;
this.owenrType = owenrType;
}
public override bool CanResetValue(object c) => false;
public override object GetValue(object c) => p.GetValue(null);
public override void ResetValue(object c) { }
public override void SetValue(object c, object v) => p.SetValue(null, v);
public override bool ShouldSerializeValue(object c) => false;
public override Type ComponentType { get { return owenrType; } }
public override bool IsReadOnly { get { return !p.CanWrite; } }
public override Type PropertyType { get { return p.PropertyType; } }
}
然后你可以使用我上面提到的任何一个选项。例如,在这里我创建了一个包装器类型描述符以不触及原始 class:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
public class CustomObjectWrapper : CustomTypeDescriptor
{
public object WrappedObject { get; private set; }
private IEnumerable<PropertyDescriptor> staticProperties;
public CustomObjectWrapper(object o)
: base(TypeDescriptor.GetProvider(o).GetTypeDescriptor(o))
{
WrappedObject = o;
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var instanceProperties = base.GetProperties(attributes)
.Cast<PropertyDescriptor>();
staticProperties = WrappedObject.GetType()
.GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(p => new StaticPropertyDescriptor(p, WrappedObject.GetType()));
return new PropertyDescriptorCollection(
instanceProperties.Union(staticProperties).ToArray());
}
}
而且用法很简单:
var myClass = new MyClass();
propertyGrid1.SelectedObject = new CustomObjectWrapper (myClass);