- 动态对象
// 动态对象实现
[TypeConverter(typeof(CategoriesSortedByClassDefinitionConverter)), CategoriesSortedByClassDefinitionConverter.ElementsSameOrder]
public class DynamicObject : ICustomTypeDescriptor
{
/// <summary>
/// 项目的英文名称
/// </summary>
public string CustomName { set; get; }
public object TagInfo { get; set; }
// private PropertyCollection _properties = new PropertyCollection();
private List<DynamicProperty> _properties = new List<DynamicProperty>();
private List<string> _categoryList = new List<string>();
public void AddProperty(string name, object value, string displayName = null, string description = null, string cateogry = "属性", bool readOnly = false, Type converterType = null, bool browsable = true, TypeConverter typeConverter = null)
{
_properties.Add(new DynamicProperty(name, value, displayName, description, cateogry, readOnly, converterType, browsable, typeConverter));
if (!string.IsNullOrEmpty(cateogry) && !_categoryList.Contains(cateogry))
{
_categoryList.Add(cateogry);
}
}
public object GetPropertyOwner(PropertyDescriptor pd) => this;
/// <summary>
/// 返回属性的集合
/// </summary>
/// <returns></returns>
public PropertyDescriptorCollection GetProperties()
{
/*var visibleProperties = _properties.Where(p => p.IsBrowsable);
return new PropertyDescriptorCollection(visibleProperties.ToArray());*/
//return new PropertyDescriptorCollection(_properties.ToArray(), true);
var arr = _properties.Where(x => x.IsBrowsable).ToArray();
return new PropertyDescriptorCollection(arr, true);
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return GetProperties();
//return new PropertyDescriptorCollection(_properties.ToArray());
}
// ICustomTypeDescriptor 其他接口方法可以选择实现空逻辑
public AttributeCollection GetAttributes() => AttributeCollection.Empty;
public string GetClassName() => null;
public string GetComponentName() => null;
public TypeConverter GetConverter() => null;
public EventDescriptor GetDefaultEvent() => null;
public PropertyDescriptor GetDefaultProperty() => null;
public object GetEditor(Type editorBaseType) => null;
public EventDescriptorCollection GetEvents() => EventDescriptorCollection.Empty;
public EventDescriptorCollection GetEvents(Attribute[] attributes) => EventDescriptorCollection.Empty;
public List<DynamicProperty> GetDynamicProperties() => _properties;
public DynamicProperty GetDynamicProperty(string name)
{
if (string.IsNullOrEmpty(name))
{
return null;
}
DynamicProperty data = null;
foreach (DynamicProperty tmp in _properties)
{
if (!tmp.Name.Equals(name))
{
continue;
}
data = tmp;
break;
}
return data;
}
public void SetPropertyReadonly(string name, bool isReadOnly)
{
foreach (var tmp in _properties)
{
if (!tmp.Name.Equals(name))
{
continue;
}
tmp.CustomIsRreadOnly = isReadOnly;
break;
}
}
public void SetPropertyBrowse(string name, bool browse)
{
foreach (var tmp in _properties)
{
if (!tmp.Name.Equals(name))
{
continue;
}
tmp.SetBrowse(browse);
break;
}
}
public void SetCustomConverter(string name, TypeConverter typeConverter)
{
foreach (var tmp in _properties)
{
if (!tmp.Name.Equals(name))
{
continue;
}
tmp.CustomTypeConverter = typeConverter;
break;
}
}
public bool RemovePropertyByName(string name)
{
if (string.IsNullOrEmpty(name))
{
return true;
}
DynamicProperty data = null;
foreach (DynamicProperty tmp in _properties)
{
if (!tmp.Name.Equals(name))
{
continue;
}
data = tmp;
break;
}
_properties.Remove(data);
return true;
}
}
2. 动态属性
// 动态属性类
public class DynamicProperty : PropertyDescriptor
{
private object _value;
private Type _converterType;
private string _displayName;
private string _category;
private bool _brows;
private string _desc;
private bool _readOnly;
private TypeConverter _typeConverter;
public bool CustomIsRreadOnly { set; get; }
public TypeConverter CustomTypeConverter { get => _typeConverter; set { _typeConverter = value; } }
/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <param name="displayName">显示名称</param>
/// <param name="description">描述</param>
/// <param name="cateogry">分类</param>
/// <param name="readlyOnly">只读</param>
/// <param name="converterType">转换器</param>
/// <param name="brows">显示</param>
public DynamicProperty(string name, object value, string displayName = null, string description = null, string cateogry = "属性", bool readlyOnly = false, Type converterType = null, bool brows = true, TypeConverter typeConverter = null) : base(name, new Attribute[0])
{
_value = value;
_converterType = converterType;
_displayName = displayName;
if (string.IsNullOrEmpty(displayName))
{
_displayName = name;
}
_category = cateogry;
_brows = brows;
_desc = description;
_readOnly = readlyOnly;
CustomIsRreadOnly = readlyOnly;
_typeConverter = typeConverter;
}
public override bool CanResetValue(object component) => false;
public override Type ComponentType => typeof(DynamicObject);
public override object GetValue(object component) => _value;
public override bool IsReadOnly => CustomIsRreadOnly;
public override Type PropertyType => _value.GetType();
public override void ResetValue(object component) { }
public override void SetValue(object component, object value) => _value = value;
public override bool ShouldSerializeValue(object component) => true;
public override TypeConverter Converter
{
get
{
/*if (_value is bool)
{
return new BooleanCheckBoxConverter();
}*/
if (_converterType != null)
{
return (TypeConverter)Activator.CreateInstance(_converterType);
}
if (_typeConverter != null)
{
return _typeConverter;
}
return base.Converter;
}
}
public override string DisplayName => _displayName;
public override string Category => _category;
public override bool IsBrowsable => _brows;
public override string Description => _desc;
public override AttributeCollection Attributes
{
get
{
var attributes = base.Attributes.Cast<Attribute>().ToList();
if (CustomIsRreadOnly)
{
attributes.Add(new ReadOnlyAttribute(true));
}
return new AttributeCollection(attributes.ToArray());
}
}
public void SetCategory(string newCategory)
{
_category = newCategory;
}
public void SetBrowse(bool val)
{
_brows = val;
}
}
3. 用法
DynamicObject gradeObj = new DynamicObject()
{
CustomName = "YourName",
TagInfo = tagInfo
};
gradeObj.AddProperty("Category", "三年级", "年级", "班级描述", "基本属性", true, null, true);
gradeObj.AddProperty("Type", "", "二班", "班级", "基本属性", true, null, true);
PropertyGrid.SelectedObject = gradeObj;
// 读取
DynamicObject customroperty = (DynamicObject)PropertyGrid.SelectedObject;
string catStr = customroperty.GetDynamicProperty("Category").GetValue("Category").ToString();
