C# 自定义(动态)属性-WPF Xceed属性网格
我需要在运行时向WPF Xceed属性网格控件添加自定义属性。我能找到的最佳解决方案如下: 但是,它仅适用于WinForms属性网格控件。请参阅下面的代码和我得到的结果 我根本不是这个领域的专家。是否可以使代码与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
/// <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; }
}