我想PerformanceCounter
通过使用 a 设置其参数来动态创建 a PropertyGrid
。如果我设置PropertyGrid.SelectedObject
为PerformanceCounter
它不提供与 IDE 中相同的选项。
我该怎么做?有可能吗?
我想PerformanceCounter
通过使用 a 设置其参数来动态创建 a PropertyGrid
。如果我设置PropertyGrid.SelectedObject
为PerformanceCounter
它不提供与 IDE 中相同的选项。
我该怎么做?有可能吗?
主要问题是某些 PerformanceCounter 属性(例如 CategoryName)标有ReadOnly属性。当属性网格在属性上看到 ReadOnly 属性时,您无法对其进行编辑,因此您可以使用包含类别名称列表的下拉列表。
我不知道设计师使用什么魔法来克服这个问题,但这是我的解决方案。我们将自定义TypeDescriptionProvider添加到已编辑的 PerformanceCounter 实例中,并提供一个自定义类型描述符以消除 ReadOnly 限制。
这是您可以使用它的方式(使用 PropertyGrid 类的 propertyGrid1 实例):
PerformanceCounter counter = new PerformanceCounter();
// use a custom type description provider for this counter
TypeDescriptor.AddProvider(new PerformanceCounterTypeProvider(), counter);
// filter unwanted properties
propertyGrid1.BrowsableAttributes = new AttributeCollection(DesignerSerializationVisibilityAttribute.Visible);
// select it in the property grid
propertyGrid1.SelectedObject = counter;
这是使用的实用程序代码:
public class PerformanceCounterTypeProvider : TypeDescriptionProvider
{
private static PropertyDescriptor[] _properties;
static PerformanceCounterTypeProvider()
{
List < PropertyDescriptor> properties = new List<PropertyDescriptor>();
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(typeof(PerformanceCounter)))
{
PerformanceCounterPropertyDescriptor clone = new PerformanceCounterPropertyDescriptor(pd);
properties.Add(clone);
}
_properties = properties.ToArray();
}
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return new PerformanceCounterTypeDescriptor();
}
private class PerformanceCounterTypeDescriptor : CustomTypeDescriptor
{
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return new PropertyDescriptorCollection(PerformanceCounterTypeProvider._properties.ToArray());
}
}
private class PerformanceCounterPropertyDescriptor : PropertyDescriptor
{
private PropertyDescriptor _desc;
public PerformanceCounterPropertyDescriptor(PropertyDescriptor desc)
: base(desc, new List<Attribute>(desc.Attributes.OfType<Attribute>()).ToArray())
{
_desc = desc;
}
public override void SetValue(object component, object value)
{
// we can't use _desc.SetValue because the underlying property descriptor checks it's read only
ComponentType.GetProperty(Name).SetValue(component, value, null);
}
public override bool IsReadOnly
{
get { return false; }
}
public override bool CanResetValue(object component)
{
return _desc.CanResetValue(component);
}
public override Type ComponentType
{
get { return _desc.ComponentType; }
}
public override object GetValue(object component)
{
return _desc.GetValue(component);
}
public override Type PropertyType
{
get { return _desc.PropertyType; }
}
public override void ResetValue(object component)
{
_desc.ResetValue(component);
}
public override bool ShouldSerializeValue(object component)
{
return _desc.ShouldSerializeValue(component);
}
}
}
根据这篇文章,有些设置在运行时无法更改。这向我表明,默认情况下,propertygrid 只会显示那些可以在运行时更改的设置,并且您在设计时看到的设置与在运行时看到的设置之间总是存在差异。