C# 自定义(动态)属性-WPF Xceed属性网格

C# 自定义(动态)属性-WPF Xceed属性网格,c#,wpf,propertygrid,xceed,C#,Wpf,Propertygrid,Xceed,我需要在运行时向WPF Xceed属性网格控件添加自定义属性。我能找到的最佳解决方案如下: 但是,它仅适用于WinForms属性网格控件。请参阅下面的代码和我得到的结果 我根本不是这个领域的专家。是否可以使代码与Xceed属性网格控件兼容 自定义类: /// <summary> /// CustomClass (Which is binding to property grid) /// </summary> public class

我需要在运行时向WPF Xceed属性网格控件添加自定义属性。我能找到的最佳解决方案如下:

但是,它仅适用于WinForms属性网格控件。请参阅下面的代码和我得到的结果

我根本不是这个领域的专家。是否可以使代码与Xceed属性网格控件兼容

自定义类:

    /// <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


    }
//
///CustomClass(绑定到属性网格)
/// 
公共类CustomClass:CollectionBase,ICustomTypeDescriptor
{
/// 
///将CustomProperty添加到Collectionbase列表
/// 
/// 
公共作废添加(CustomProperty值)
{
base.List.Add(值);
}
/// 
///从列表中删除项目
/// 
/// 
公共无效删除(字符串名称)
{
foreach(基本列表中的CustomProperty属性)
{
如果(prop.Name==Name)
{
基本。列表。移除(道具);
返回;
}
}
}
/// 
///索引器
/// 
公共CustomProperty此[int索引]
{
得到
{
返回(CustomProperty)基列表[索引];
}
设置
{
基本列表[索引]=(CustomProperty)值;
}
}
#区域“类型描述符实现”
/// 
///获取类名
/// 
///串
公共字符串GetClassName()
{
返回TypeDescriptor.GetClassName(此为true);
}
/// 
///获取属性
/// 
///属性集合
公共属性集合GetAttributes()
{
返回TypeDescriptor.GetAttributes(this,true);
}
/// 
///GetComponentName
/// 
///串
公共字符串GetComponentName()
{
返回TypeDescriptor.GetComponentName(此为true);
}
/// 
///GetConverter
/// 
///类型转换器
公共类型转换器GetConverter()
{
返回TypeDescriptor.GetConverter(此为true);
}
/// 
///GetDefaultEvent
/// 
///事件描述符
公共事件描述符GetDefaultEvent()
{
返回TypeDescriptor.GetDefaultEvent(this,true);
}
/// 
///GetDefaultProperty
/// 
///PropertyDescriptor
公共属性描述程序GetDefaultProperty()
{
返回TypeDescriptor.GetDefaultProperty(this,true);
}
/// 
///GetEditor
/// 
///editorBaseType
///反对
公共对象GetEditor(类型editorBaseType)
{
返回TypeDescriptor.GetEditor(this,editorBaseType,true);
}
公共事件描述符集合GetEvents(属性[]属性)
{
返回TypeDescriptor.GetEvents(this,attributes,true);
}
公共事件描述符集合GetEvents()
{
返回TypeDescriptor.GetEvents(this,true);
}
公共属性DescriptorCollection GetProperties(属性[]属性)
{
PropertyDescriptor[]newProps=newPropertyDescriptor[this.Count];
for(int i=0;i    /// <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


    }
CustomClass myProperties = new CustomClass();
propertyGrid.AutoGenerateProperties = false;
propertyGrid.SelectedObject = myProperties;
propertyGrid.PropertyDefinitions.Add(new Xceed.Wpf.Toolkit.PropertyGrid.PropertyDefinition() { Category = "Cat1", DisplayName = "Name", TargetProperties = new string[] { "Name"} });
 public class EntityProperties : ICustomTypeDescriptor
    {
        public List<MyProperty> myProperties = new List<MyProperty>();

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
        {
            // Create a collection object to hold property descriptors
            PropertyDescriptorCollection pds = new PropertyDescriptorCollection(null);

            for (int i = 0; i < myProperties.Count; i++)
            {
                pds.Add(new MyPropertyDescriptor(myProperties[i], this));
            }

            return pds;
        }


        #region Use default TypeDescriptor stuff

        AttributeCollection ICustomTypeDescriptor.GetAttributes()
        {
            return TypeDescriptor.GetAttributes(this, noCustomTypeDesc: true);
        }

        string ICustomTypeDescriptor.GetClassName()
        {
            return TypeDescriptor.GetClassName(this, noCustomTypeDesc: true);
        }

        string ICustomTypeDescriptor.GetComponentName()
        {
            return TypeDescriptor.GetComponentName(this, noCustomTypeDesc: true);
        }

        TypeConverter ICustomTypeDescriptor.GetConverter()
        {
            return TypeDescriptor.GetConverter(this, noCustomTypeDesc: true);
        }

        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
        {
            return TypeDescriptor.GetDefaultEvent(this, noCustomTypeDesc: true);
        }

        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
        {
            return TypeDescriptor.GetDefaultProperty(this, noCustomTypeDesc: true);
        }

        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
        {
            return TypeDescriptor.GetEditor(this, editorBaseType, noCustomTypeDesc: true);
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
        {
            return TypeDescriptor.GetEvents(this, noCustomTypeDesc: true);
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(this, attributes, noCustomTypeDesc: true);
        }

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
        {
            return TypeDescriptor.GetProperties(this, attributes, noCustomTypeDesc: true);
        }

        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }

        #endregion
    }
public class MyPropertyDescriptor: PropertyDescriptor
    {

        MyProperty _prop;
        object _parent;
        public MyPropertyDescriptor(MyProperty prop, object parent)
          : base(prop.PropertyName, null)
        {
            _prop = prop;
            _parent = parent;
        }

        public override AttributeCollection Attributes
        {
            get
            {
                var attributes = TypeDescriptor.GetAttributes(GetValue(null), false);

                return attributes;
            }
        }

        public override bool CanResetValue(object component)
        {
            return false;
        }

        public override object GetValue(object component)
        {
            switch (_prop.Type)
            {
                case MyProperty.PropertyType.String:
                    return _prop.StringValue;
                case MyProperty.PropertyType.Number:
                    return _prop.NumberValue;
                default:
                    break;
            }
            return null;
        }



        public override void ResetValue(object component)
        {
            throw new NotImplementedException();
        }

        public override void SetValue(object component, object value)
        {
            switch (_prop.Type)
            {
                case MyProperty.PropertyType.String:
                    _prop.StringValue = value as string;
                    break;
                case MyProperty.PropertyType.Number:
                    _prop.NumberValue = (double)value;
                    break;
                default:
                    break;
            }
        }

        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }

        public override Type ComponentType
          => _parent.GetType();

        public override bool IsReadOnly
          => false;

        public override Type PropertyType
        {
            get
            {
                switch (_prop.Type)
                {
                    case MyProperty.PropertyType.String:
                        return _prop.StringValue.GetType();
                    case MyProperty.PropertyType.Number:
                        return _prop.NumberValue.GetType();
                    default:
                        return typeof(string);
                }
            }
        }
    }
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        EntityProperties pp = new EntityProperties()
        {
            myProperties = new List<MyProperty>()
            {
                new MyProperty() { Type = MyProperty.PropertyType.String, StringValue = "simple", PropertyName = "EntityType" },
                new MyProperty() { Type = MyProperty.PropertyType.Number, NumberValue = 123, PropertyName = "EntityID" }
            }
        };


        _propertyGrid.SelectedObject = pp;

        _propertyGrid.AutoGenerateProperties = true;
    }
    }
public class MyProperty
{
    public enum PropertyType
    {
        String,
        Number
    }

    public PropertyType Type { get; set; }

    public string StringValue { get; set; }

    public double NumberValue { get; set; }

    public string PropertyName { get; set; }

}