Search code examples
c#custom-attributespropertygrid

Changing the display names in a propertygrid


I am creating a List<> of a Test class, I made. I then convert it to an array and assign it to a propertygrid control.

    List<Test> lc_Test;
    public class Test : UserControl
    {
        [Category("lc_Test"), Description("Testing using List<>, for storage."), DisplayName("Images")]
        public Image img { get; set; }
    }

    // Above in Form1(), I create it
    // lc_Test = new List<Test>();

    private void button7_Click(object sender, EventArgs e)
    {
        lc_Test.Clear();

        lc_Test.Add(new Test());
        lc_Test.Add(new Test());

        lc_Test[0].img = pb1.Image;
        lc_Test[1].img = pb2.Image;

        MessageBox.Show(lc_Test.Count.ToString());

        pgTest.SelectedObject = lc_Test.ToArray();
    }

As seen in the picture, it works:

enter image description here

I am now wondering, if there is any way to change the Display Name of each item. Cause, it names them "(0)" and "(1)". In this test, I'd like to change it to say. "Test Item 0" and "Test Item 1". I need to change the "Help Text" for each item, also. Got to be a way.

Anyone, need anything from me let me know.


Solution

  • Solution:

    enter image description here

    Your form1.cs code file:

    using System;
    using System.Windows.Forms;
    
    namespace PropertyGridSample
    {
        public class Form1 : System.Windows.Forms.Form
        {
            Layers layers_test;
    
            internal System.Windows.Forms.PropertyGrid PropertyGrid1;
    
            private System.ComponentModel.Container components = null; //Required designer variable
    
            public Form1()
            {
                InitializeComponent();
    
                layers_test = new Layers();
                PropertyGrid1.SelectedObject = layers_test;
            }
    
            // Clean up any resources being used
            protected override void Dispose( bool disposing )
            {
                if (disposing) { if (components != null) { components.Dispose(); } }
    
                base.Dispose( disposing );
            }
    
            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
                this.PropertyGrid1 = new System.Windows.Forms.PropertyGrid();
                this.SuspendLayout();
                // 
                // PropertyGrid1
                // 
                this.PropertyGrid1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right)));
                this.PropertyGrid1.LineColor = System.Drawing.SystemColors.ScrollBar;
                this.PropertyGrid1.Location = new System.Drawing.Point(0, -1);
                this.PropertyGrid1.Name = "PropertyGrid1";
                this.PropertyGrid1.PropertySort = System.Windows.Forms.PropertySort.Alphabetical;
                this.PropertyGrid1.Size = new System.Drawing.Size(408, 254);
                this.PropertyGrid1.TabIndex = 1;
                this.PropertyGrid1.ToolbarVisible = false;
                this.PropertyGrid1.SelectedGridItemChanged += new System.Windows.Forms.SelectedGridItemChangedEventHandler(this.PropertyGrid1_SelectedGridItemChanged);
                // 
                // Form1
                // 
                this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                this.ClientSize = new System.Drawing.Size(408, 254);
                this.Controls.Add(this.PropertyGrid1);
                this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
                this.MaximizeBox = false;
                this.Name = "Form1";
                this.Text = "Customizing Collections in Property Grid Demo";
                this.ResumeLayout(false);
    
            }
            #endregion
    
            [STAThread]
            static void Main() 
            {
                Application.Run(new Form1());
            }
    
            private void PropertyGrid1_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
            {
                PropertyGrid1.Refresh();
            }
        }
    }
    

    I made a separate cs file, called LayerCollection.cs:

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    
    namespace PropertyGridSample
    {
        [TypeConverter(typeof(LayerConverter))]
        public class Layer
        {
            public Image image { get; set; }
    
            public Layer() { }
        }
    
        public class Layers
        {
            LayerCollection layercollection = new LayerCollection();
    
            public Layers()
            {
                Layer[] layz = new Layer[2];
    
                Layer lay1 = new Layer(); Layer lay2 = new Layer(); //Create two test layers and add them to the layer collection
    
                layercollection.Add(lay1); layercollection.Add(lay2);
            }
    
            [TypeConverter(typeof(LayerCollectionConverter))]
            public LayerCollection Layer_Collection { get { return layercollection; } }
        }
    
        public class LayerCollection : CollectionBase, ICustomTypeDescriptor
        {
            #region collection impl
                public void Add(Layer lay) { List.Add(lay); } //Adds a layer object to the collection
                public void Remove(Layer lay) { List.Remove(lay); } //Removes a layer object from the collection
    
                public Layer this[int index] { get { return (List.Count > -1 && index < List.Count) ? (Layer)List[index] : null; } } //Return a layer object at index position
            #endregion
    
            #region ICustomTypeDescriptor impl 
                public AttributeCollection GetAttributes() { return TypeDescriptor.GetAttributes(this, true); }
    
                public String GetClassName() { return TypeDescriptor.GetClassName(this, true); }
                public String GetComponentName() { return TypeDescriptor.GetComponentName(this, true); }
    
                public TypeConverter GetConverter() { return TypeDescriptor.GetConverter(this, true); }
    
                public EventDescriptor GetDefaultEvent() { return TypeDescriptor.GetDefaultEvent(this, true); }
                public PropertyDescriptor GetDefaultProperty() { return TypeDescriptor.GetDefaultProperty(this, true); }
    
                public EventDescriptorCollection GetEvents(Attribute[] attributes) { return TypeDescriptor.GetEvents(this, attributes, true); }
                public EventDescriptorCollection GetEvents() { return TypeDescriptor.GetEvents(this, true); }
    
                public object GetEditor(Type editorBaseType) { return TypeDescriptor.GetEditor(this, editorBaseType, true); }
                public object GetPropertyOwner(PropertyDescriptor pd) { return this; }
    
                //Called to get the properties of this type. Returns properties with certain attributes. this restriction is not implemented here.
                public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { return GetProperties(); }
    
                //Called to get the properties of this type.
                public PropertyDescriptorCollection GetProperties()
                {            
                    PropertyDescriptorCollection pds = new PropertyDescriptorCollection(null); // Create a collection object to hold property descriptors
    
                    // Iterate the list of layers and create a property descriptor for each layer item and add to the property descriptor collection
                    for (int i = 0; i < this.List.Count; i++) { LayerCollectionPropertyDescriptor pd = new LayerCollectionPropertyDescriptor(this, i); pds.Add(pd); }
    
                    return pds; // return the descriptor collection
                }
            #endregion
        }
    
        class LayerConverter : ExpandableObjectConverter
        {
            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destType)
            {
                return (destType == typeof(string) && value is Layer) ? "Layer Data": base.ConvertTo(context, culture, value, destType);
            }
        }
    
        class LayerCollectionConverter : ExpandableObjectConverter
        {
            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destType)
            {
                return  (destType == typeof(string) && value is LayerCollection) ? "Items": base.ConvertTo(context, culture, value, destType);
            }
        }
    
        public class LayerCollectionPropertyDescriptor : PropertyDescriptor
        {
            private LayerCollection collection = null;
            private int index = -1;
    
            public LayerCollectionPropertyDescriptor(LayerCollection coll, int idx) : base("#" + idx.ToString(), null)
            {
                collection = coll; index = idx;
            }
    
            public override AttributeCollection Attributes { get { return new AttributeCollection(null); } }
    
            public override bool CanResetValue(object component) { return true; }
            public override bool IsReadOnly { get { return false; } }
            public override bool ShouldSerializeValue(object component) { return true; }
    
            public override string Description { get { return "Layer Description"; } }
            public override string DisplayName { get { return "Layer " + index.ToString(); } }
            public override string Name { get { return "#" + index.ToString(); } }
    
            public override object GetValue(object component) { return collection[index]; }
    
            public override Type ComponentType { get { return collection.GetType(); } }
            public override Type PropertyType { get { return collection[index].GetType(); } }
    
            public override void ResetValue(object component) { }
            public override void SetValue(object component, object value) { } // this.collection[index] = value;
        }
    }
    

    On your form, you just need to throw a propertygrid on it. I'm still looking at ways to improve it and need the ability to trap the add and remove buttons, on the built in collection editor

    enter image description here