How to display a dynamic object in property grid?

后端 未结 3 996
时光取名叫无心
时光取名叫无心 2021-01-01 04:57

I have a custom object type which has to be editable in PropertyGrid:

public class CustomObjectType
{
    public string Name { get; set; }               


        
3条回答
  •  盖世英雄少女心
    2021-01-01 05:37

    To go down this route, you would need to create a custom PropertyDescriptor per property. You would then expose that via a custom TypeConverter, or (alternatively) ICustomTypeDescriptor/TypeDescriptionProvider. Example:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows.Forms;
    [TypeConverter(typeof(CustomObjectType.CustomObjectConverter))]
    public class CustomObjectType
    {
        [Category("Standard")]
        public string Name { get; set; }
        private readonly List props = new List();
        [Browsable(false)]
        public List Properties { get { return props; } }
    
        private Dictionary values = new Dictionary();
    
        public object this[string name]
        {
            get { object val; values.TryGetValue(name, out val); return val; }
            set { values.Remove(name); }
        }
    
        private class CustomObjectConverter : ExpandableObjectConverter
        {
            public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
            {
                var stdProps = base.GetProperties(context, value, attributes);
                CustomObjectType obj = value as CustomObjectType;
                List customProps = obj == null ? null : obj.Properties;
                PropertyDescriptor[] props = new PropertyDescriptor[stdProps.Count + (customProps == null ? 0 : customProps.Count)];
                stdProps.CopyTo(props, 0);
                if (customProps != null)
                {
                    int index = stdProps.Count;
                    foreach (CustomProperty prop in customProps)
                    {
                        props[index++] = new CustomPropertyDescriptor(prop);
                    }
                }
                return new PropertyDescriptorCollection(props);
            }
        }
        private class CustomPropertyDescriptor : PropertyDescriptor
        {
            private readonly CustomProperty prop;
            public CustomPropertyDescriptor(CustomProperty prop) : base(prop.Name, null)
            {
                this.prop = prop;
            }
            public override string Category { get { return "Dynamic"; } }
            public override string Description { get { return prop.Desc; } }
            public override string Name { get { return prop.Name; } }
            public override bool ShouldSerializeValue(object component) { return ((CustomObjectType)component)[prop.Name] != null; }
            public override void ResetValue(object component) { ((CustomObjectType)component)[prop.Name] = null; }
            public override bool IsReadOnly { get { return false; } }
            public override Type PropertyType { get { return prop.Type; } }
            public override bool CanResetValue(object component) { return true; }
            public override Type ComponentType { get { return typeof(CustomObjectType); } }
            public override void SetValue(object component, object value) { ((CustomObjectType)component)[prop.Name] = value; }
            public override object GetValue(object component) { return ((CustomObjectType)component)[prop.Name] ?? prop.DefaultValue; }
        }
    }
    
    
    public class CustomProperty
    {
        public string Name { get; set; }
        public string Desc { get; set; }
        public object DefaultValue { get; set; }
        Type type;
    
        public Type Type
        {
            get
            {
                return type;
            }
            set
            {
                    type = value;
                    DefaultValue = Activator.CreateInstance(value);
            }              
        }
    }
    
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            var obj = new CustomObjectType
            {
                Name = "Foo",
                Properties =
                {
                    new CustomProperty { Name = "Bar", Type = typeof(int), Desc = "I'm a bar"},
                    new CustomProperty { Name = "When", Type = typeof(DateTime), Desc = "When it happened"},
                }
            };
            Application.Run(new Form { Controls = { new PropertyGrid { SelectedObject = obj, Dock = DockStyle.Fill } } });
        }
    }
    

提交回复
热议问题