I need to add custom properties to the WPF Xceed Property Grid control during runtime. The best solution that I could find is the one presented here:
How to modify PropertyGrid at runtime (add/remove property and dynamic types/enums)
However it only works for the WinForms Property Grid control. See below for code, and the result that I am getting.
I'm not an expert in this field at all. Is it possible to make the code compatible with the Xceed Property Grid control?
        CustomClass myProperties = new CustomClass();
        propertyGrid.SelectedObject = myProperties;
        myProperties.Add(new CustomProperty("Name", "Sven", typeof(string), false, true,"Cat1"));
        myProperties.Add(new CustomProperty("Surname", "Bendo", typeof(string), false, true, "Cat1"));
        myProperties.Add(new CustomProperty("Card", "Visa", typeof(string), false, true, "Cat2"));
        myProperties.Add(new CustomProperty("Bank", "SB", typeof(string), false, true, "Cat2"));
        propertyGrid.Update();
Custom class:
    /// <summary>
    /// CustomClass (Which is binding to property grid)
    /// </summary>
    public class CustomClass : CollectionBase, ICustomTypeDescriptor
    {
        /// <summary>
        /// Add CustomProperty to Collectionbase List
        /// </summary>
        /// <param name="Value"></param>
        public void Add(CustomProperty Value)
        {
            base.List.Add(Value);
        }
        /// <summary>
        /// Remove item from List
        /// </summary>
        /// <param name="Name"></param>
        public void Remove(string Name)
        {
            foreach (CustomProperty prop in base.List)
            {
                if (prop.Name == Name)
                {
                    base.List.Remove(prop);
                    return;
                }
            }
        }
        /// <summary>
        /// Indexer
        /// </summary>
        public CustomProperty this[int index]
        {
            get
            {
                return (CustomProperty)base.List[index];
            }
            set
            {
                base.List[index] = (CustomProperty)value;
            }
        }
        #region "TypeDescriptor Implementation"
        /// <summary>
        /// Get Class Name
        /// </summary>
        /// <returns>String</returns>
        public String GetClassName()
        {
            return TypeDescriptor.GetClassName(this, true);
        }
        /// <summary>
        /// GetAttributes
        /// </summary>
        /// <returns>AttributeCollection</returns>
        public AttributeCollection GetAttributes()
        {
            return TypeDescriptor.GetAttributes(this, true);
        }
        /// <summary>
        /// GetComponentName
        /// </summary>
        /// <returns>String</returns>
        public String GetComponentName()
        {
            return TypeDescriptor.GetComponentName(this, true);
        }
        /// <summary>
        /// GetConverter
        /// </summary>
        /// <returns>TypeConverter</returns>
        public TypeConverter GetConverter()
        {
            return TypeDescriptor.GetConverter(this, true);
        }
        /// <summary>
        /// GetDefaultEvent
        /// </summary>
        /// <returns>EventDescriptor</returns>
        public EventDescriptor GetDefaultEvent()
        {
            return TypeDescriptor.GetDefaultEvent(this, true);
        }
        /// <summary>
        /// GetDefaultProperty
        /// </summary>
        /// <returns>PropertyDescriptor</returns>
        public PropertyDescriptor GetDefaultProperty()
        {
            return TypeDescriptor.GetDefaultProperty(this, true);
        }
        /// <summary>
        /// GetEditor
        /// </summary>
        /// <param name="editorBaseType">editorBaseType</param>
        /// <returns>object</returns>
        public object GetEditor(Type editorBaseType)
        {
            return TypeDescriptor.GetEditor(this, editorBaseType, true);
        }
        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(this, attributes, true);
        }
        public EventDescriptorCollection GetEvents()
        {
            return TypeDescriptor.GetEvents(this, true);
        }
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            PropertyDescriptor[] newProps = new PropertyDescriptor[this.Count];
            for (int i = 0; i < this.Count; i++)
            {
                CustomProperty prop = (CustomProperty)this[i];
                newProps[i] = new CustomPropertyDescriptor(ref prop, attributes);
            }
            return new PropertyDescriptorCollection(newProps);
        }
        public PropertyDescriptorCollection GetProperties()
        {
            return TypeDescriptor.GetProperties(this, true);
        }
        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }
        #endregion
    }
    /// <summary>
    /// Custom property class 
    /// </summary>
    public class CustomProperty
    {
        private string sName = string.Empty;
        private string sCategory = "";
        private bool bReadOnly = false;
        private bool bVisible = true;
        private object objValue = null;
        public CustomProperty(string sName, object value, Type type, bool bReadOnly, bool bVisible,string sCategory)
        {
            this.sName = sName;
            this.objValue = value;
            this.type = type;
            this.bReadOnly = bReadOnly;
            this.bVisible = bVisible;
            this.sCategory = sCategory;
        }
        private Type type;
        public Type Type
        {
            get { return type; }
        }
        public bool ReadOnly
        {
            get
            {
                return bReadOnly;
            }
        }
        public string Name
        {
            get
            {
                return sName;
            }
        }
        public string Category
        {
            get
            {
                return sCategory;
            }
        }
        public bool Visible
        {
            get
            {
                return bVisible;
            }
        }
        public object Value
        {
            get
            {
                return objValue;
            }
            set
            {
                objValue = value;
            }
        }
    }
    /// <summary>
    /// Custom PropertyDescriptor
    /// </summary>
    public class CustomPropertyDescriptor : PropertyDescriptor
    {
        CustomProperty m_Property;
        public CustomPropertyDescriptor(ref CustomProperty myProperty, Attribute[] attrs) : base(myProperty.Name, attrs)
        {
            m_Property = myProperty;
        }
        #region PropertyDescriptor specific
        public override bool CanResetValue(object component)
        {
            return false;
        }
        public override Type ComponentType
        {
            get { return null; }
        }
        public override object GetValue(object component)
        {
            return m_Property.Value;
        }
        public override string Description
        {
            get { return m_Property.Name; }
        }
        public override string Category
        {
            get { return m_Property.Category; }
        }
        public override string DisplayName
        {
            get { return m_Property.Name; }
        }
        public override bool IsReadOnly
        {
            get { return m_Property.ReadOnly; }
        }
        public override void ResetValue(object component)
        {
            //Have to implement
        }
        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }
        public override void SetValue(object component, object value)
        {
            m_Property.Value = value;
        }
        public override Type PropertyType
        {
            get { return m_Property.Type; }
        }
        #endregion
    }
