使用PropertyGrid设置PerformanceCounter

3
我希望能够通过使用PropertyGrid设置参数,动态创建PerformanceCounter。如果我将PropertyGrid.SelectedObject设置为PerformanceCounter,它提供的选项与IDE中不同。
如何实现这个技巧?这是否可能?

在属性窗口中添加的属性是特定于设计师的。例如GenerateMember,您不会在PropertyGrid中生成成员。非常不清楚为什么您认为这是个问题。 - Hans Passant
我不认为这是个问题。我想要存档与设计师所见相同的东西,并想知道如何做到。 - Pho3nixHun
抱歉,我的意思是*实现。 - Pho3nixHun
2个回答

1
主要问题在于一些PerformanceCounter属性(例如CategoryName)被标记为ReadOnly属性。当属性网格看到属性上有ReadOnly属性时,您无法编辑它,因此您无法使用下拉列表查看类别名称列表。
我不知道设计师如何克服这个问题,但这是我的解决方案。我们向正在编辑的PerformanceCounter实例添加自定义TypeDescriptionProvider,并提供一个自定义类型描述符以删除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);
        }
    }
}

谢谢,我已经检查过了,GetValue例程抛出类别名称丢失的错误。你能否请再检查一下? - Pho3nixHun

0
根据这篇文章,有一些设置在运行时无法更改。这意味着默认情况下,属性网格将仅显示那些可以在运行时更改的设置,并且设计时看到的设置与运行时看到的设置之间始终存在差异。

我想更改“CatergoryName”、“CounterName” 、“InstanceName”和“MachineName”。这些都可以在运行时更改。我只是想知道是否有一般解决方案(例如:设置类或结构),用于使用“PropertyGrid”设置“PerformanceCounter”。 - Pho3nixHun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接