See the question and my original answer on StackOverflow

The 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);
        }
    }
}