Setting up PerformanceCounter with PropertyGrid
See the question and my original answer on StackOverflowThe main issue is some PerformanceCounter properties such as CategoryName are marked with the ReadOnly attribute. When the property grid sees a ReadOnly attribute on a property, you can't edit it, so you can' have the drop down with the list of category names.
I don't know how what magic the designer uses to overcome this, but here is my solution. We add a custom TypeDescriptionProvider to the instance of PerformanceCounter edited, and provide a custom type descriptor that removes the ReadOnly limitation.
This is how you can use it (with a propertyGrid1 instance of the PropertyGrid class):
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;
And this is the utility code used:
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);
}
}
}