using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Collections; using System.Reflection; using System.Drawing.Design; using System.Windows.Forms.Design; using CommonLang.Property; using System.Windows.Forms; using System.Globalization; using System.Drawing; using CommonLang; namespace CommonFroms.G2D.DataGrid { // -------------------------------------------------------------------------------------- public interface IG2DPropertyAdapter { UITypeEditor GetEditor(MemberInfo field, Type fieldType, object ownerData); TypeConverter GetConverter(MemberInfo field, Type fieldType, object ownerData); } public interface IG2DPropertyDescriptor { object ComponentData { get; } object FieldValue { get; } bool NotNull { get; } Type DecleardFieldType { get; } } public class G2DPropertyDescriptor : ICustomTypeDescriptor { static G2DPropertyDescriptor() { RegistPropertyAdapter(new InternalDataAdapters()); } private object Data; private List adapter_list = new List(); private IG2DPropertyAdapter[] add_adapters; public G2DPropertyDescriptor(object obj, params IG2DPropertyAdapter[] adds) { this.EnablePropertyInfo = false; this.EnableFieldInfo = true; this.Data = obj; this.add_adapters = adds; foreach (IG2DPropertyAdapter sa in static_adapters) { this.AddPropertyAdapter(sa); } foreach (IG2DPropertyAdapter sa in adds) { this.AddPropertyAdapter(sa); } } public object EditData { get { return Data; } internal set { Data = value; } } public bool EnablePropertyInfo { get; set; } public bool EnableFieldInfo { get; set; } public override string ToString() { return Data.ToString(); } public void AddPropertyAdapter(IG2DPropertyAdapter adapter) { if (!adapter_list.Contains(adapter)) { adapter_list.Add(adapter); } } //------------------------------------------------------------------ #region ICustomTypeDescriptor 成员 AttributeCollection ICustomTypeDescriptor.GetAttributes() { return TypeDescriptor.GetAttributes(Data, true); } string ICustomTypeDescriptor.GetClassName() { return TypeDescriptor.GetClassName(Data, true); } string ICustomTypeDescriptor.GetComponentName() { return TypeDescriptor.GetComponentName(Data, true); } TypeConverter ICustomTypeDescriptor.GetConverter() { return TypeDescriptor.GetConverter(Data, true); } EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { return TypeDescriptor.GetDefaultEvent(Data, true); } PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { return TypeDescriptor.GetDefaultProperty(Data, true); } object ICustomTypeDescriptor.GetEditor(Type editorBaseType) { return TypeDescriptor.GetEditor(Data, editorBaseType, true); } EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { return TypeDescriptor.GetEvents(Data, attributes, true); } EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { return TypeDescriptor.GetEvents(Data, true); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { return ListPropertyDescriptors(Data, this, attributes); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { return ListPropertyDescriptors(Data, this, new Attribute[0]); } object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { return Data; } #endregion //------------------------------------------------------------------ #region StaticUtils public static bool IsNeedG2DEditor(Type listType) { if (listType.IsArray && listType.GetArrayRank() == 1) { return IsNeedG2DCollectionEditor(listType); } else if (typeof(IList).IsAssignableFrom(listType)) { return IsNeedG2DCollectionEditor(listType); } else if (typeof(IDictionary).IsAssignableFrom(listType)) { return IsNeedG2DCollectionEditor(listType); } if (listType.Equals(typeof(string))) { return false; } if (listType.IsArray) { return false; } if (listType.IsPrimitive) { return false; } return true; } public static bool IsNeedG2DCollectionEditor(Type listType) { if (listType.IsArray && listType.GetArrayRank() == 1) { Type elementType = listType.GetElementType(); return IsNeedG2DEditor(elementType); } else if (listType.GetInterface(typeof(IList).Name) != null) { if (listType.IsGenericType) { Type elementType = listType.GetGenericArguments()[0]; return IsNeedG2DEditor(elementType); } else { return true; } } else if (listType.GetInterface(typeof(IDictionary).Name) != null) { if (listType.IsGenericType) { var gtypes = listType.GetGenericArguments(); if (gtypes[0].IsPrimitive || gtypes[0] == typeof(string)) { return IsNeedG2DEditor(gtypes[1]); } } } return false; } private static List static_adapters = new List(); public static void RegistPropertyAdapter(IG2DPropertyAdapter adapter) { if (!static_adapters.Contains(adapter)) { static_adapters.Add(adapter); } } public static GridItemCollection GetAllGridEntries(PropertyGrid grid) { if (grid == null) throw new ArgumentNullException("grid"); object view = grid.GetType().GetField( "gridView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(grid); return (GridItemCollection)view.GetType().InvokeMember( "GetAllGridEntries", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, view, null); } public static void ToDescription(StringBuilder sb, object fieldValue) { if (fieldValue != null) { if (fieldValue.GetType().IsArray) { sb.AppendLine(CUtils.ArrayToString((Array)fieldValue)); } else if (fieldValue.GetType().GetInterface(typeof(IDictionary).Name) != null) { sb.AppendLine(CUtils.MapToString((IDictionary)fieldValue)); } else if (fieldValue.GetType().GetInterface(typeof(IList).Name) != null) { sb.AppendLine(CUtils.ListToString((IList)fieldValue)); } else { if (fieldValue.GetType().IsEnum) { DescAttribute eda = PropertyUtil.GetEnumAttribute((Enum)fieldValue); if (eda != null) { sb.AppendLine(fieldValue + " : " + eda.Desc); } else { sb.AppendLine(fieldValue + ""); } } else { sb.AppendLine(fieldValue + ""); } } } } #endregion //-------------------------------------------------------------------------------------------------------------------------------------------- public virtual PropertyDescriptorCollection ListPropertyDescriptors(object data, G2DPropertyDescriptor g2ddesc, Attribute[] attributes) { Type type = data.GetType(); List ret = new List(); if (type.IsArray && type.GetArrayRank() == 1) { Array array = data as Array; Type elementType = type.GetElementType(); for (int i = 0; i < array.Length; i++) { ret.Add(new ArrayItemPropertyDescriptor(g2ddesc, array, i, attributes)); } } else if (type.GetInterface(typeof(IList).Name) != null) { IList list = data as IList; if (type.IsGenericType) { Type elementType = type.GetGenericArguments()[0]; for (int i = 0; i < list.Count; i++) { ret.Add(new ListItemPropertyDescriptor(g2ddesc, list, i, attributes)); } } else { for (int i = 0; i < list.Count; i++) { ret.Add(new ListItemPropertyDescriptor(g2ddesc, list, i, attributes)); } } } else if (type.GetInterface(typeof(IDictionary).Name) != null) { IDictionary map = data as IDictionary; if (type.IsGenericType) { foreach (var k in map.Keys) { ret.Add(new MapItemPropertyDescriptor(g2ddesc, map, k, attributes)); } } } else if ((data == Data) && (type.IsEnum)) { ret.Add(new EnumPropertyDescriptor(g2ddesc, Data, attributes)); } else { if (EnableFieldInfo) { FieldInfo[] fields = type.GetFields(); for (int i = 0; i < fields.Length; i++) { FieldInfo field = fields[i]; DescAttribute desc = PropertyUtil.GetDesc(field); if (desc == null || desc.Editable) { Type fieldType = field.FieldType; object fieldData = field.GetValue(data); if (fieldData != null) { fieldType = fieldData.GetType(); } ret.Add(new FieldMemberDescriptor(g2ddesc, i, field, data, attributes)); } } } if (EnablePropertyInfo) { PropertyInfo[] props = type.GetProperties(); for (int i = 0; i < props.Length; i++) { PropertyInfo field = props[i]; DescAttribute desc = PropertyUtil.GetDesc(field); if (desc == null || desc.Editable) { Type fieldType = field.PropertyType; object fieldData = PropertyUtil.GetMemberValue(field, data); ;//field.GetValue(data); if (fieldData != null) { fieldType = fieldData.GetType(); } ret.Add(new PropertyMemberDescriptor(g2ddesc, i, field, data, attributes)); } } } } PropertyDescriptorCollection result = new PropertyDescriptorCollection(ret.ToArray(), true); ArrayList propertyNames = new ArrayList(); foreach (PropertyDescriptor propertyAttributes in ret) { propertyNames.Add(propertyAttributes.DisplayName); } return result.Sort((string[])propertyNames.ToArray(typeof(string))); } //-------------------------------------------------------------------------------------------------------------------------------------------- public abstract class MemberPropertyDescriptor : PropertyDescriptor, IG2DPropertyDescriptor where M : MemberInfo { public readonly int index; public readonly G2DPropertyDescriptor g2ddesc; protected readonly M field; protected readonly Type fieldType; protected readonly object componentData; protected readonly Type componentType; private DescAttribute desc; private DependOnPropertyAttribute[] depends; private TypeConverterAttribute[] type_converters; private ExpandableAttribute[] expandables; private ExpandableAttribute[] expandables_f; private NotNullAttribute notNull; public MemberPropertyDescriptor(G2DPropertyDescriptor g2ddesc, int index, M field, object componentData, Attribute[] attributes) : base(field.Name, attributes) { this.g2ddesc = g2ddesc; this.index = index; this.componentData = componentData; this.componentType = componentData.GetType(); this.field = field; this.fieldType = DecleardFieldType; this.desc = PropertyUtil.GetDesc(field); object fieldValue = this.GetValue(componentData); if (fieldValue != null) { fieldType = fieldValue.GetType(); } this.depends = (DependOnPropertyAttribute[])field.GetCustomAttributes(typeof(DependOnPropertyAttribute), false); this.type_converters = (TypeConverterAttribute[])fieldType.GetCustomAttributes(typeof(TypeConverterAttribute), true); this.expandables = (ExpandableAttribute[])fieldType.GetCustomAttributes(typeof(ExpandableAttribute), true); this.expandables_f = (ExpandableAttribute[])field.GetCustomAttributes(typeof(ExpandableAttribute), true); this.notNull = PropertyUtil.GetAttribute(field); } public abstract Type DecleardFieldType { get; } public M Field { get { return field; } } public object ComponentData { get { return componentData; } } public bool NotNull { get { return notNull != null; } } public object FieldValue { get { return this.GetValue(componentData); } } public override Type ComponentType { get { return componentType; } } public override bool IsReadOnly { get { if (depends != null && depends.Length > 0) { foreach (DependOnPropertyAttribute depend in depends) { bool expect = PropertyUtil.GetFieldOrPropertyOrMethodValue(componentData, depend.PropertyName); if (expect != depend.Expect) { return true; } } } return false; } } public override Type PropertyType { get { return (IsReadOnly) ? typeof(string) : fieldType; } } public override string DisplayName { get { return base.DisplayName; } } public override string Description { get { StringBuilder sb = new StringBuilder(); if (desc != null) { sb.AppendLine(desc.Desc); } object fieldValue = this.GetValue(componentData); ToDescription(sb, fieldValue); sb.AppendLine(base.Description); return sb.ToString(); } } public override string Category { get { if (desc != null) { return desc.Category; } return base.Category; } } public override bool CanResetValue(object component) { return false; } public override void ResetValue(object component) { } public override bool ShouldSerializeValue(object component) { return false; } public override object GetEditor(Type editorBaseType) { if (IsReadOnly) return null; foreach (IG2DPropertyAdapter adapter in g2ddesc.adapter_list) { UITypeEditor editor = adapter.GetEditor(field, DecleardFieldType, componentData); if (editor != null) { return editor; } } if (IsNeedG2DCollectionEditor(fieldType)) { return new G2DFieldMemberEditor(field, this.GetValue(componentData), true, g2ddesc.add_adapters); } else if (IsNeedG2DEditor(fieldType)) { return new G2DFieldMemberEditor(field, this.GetValue(componentData), false, g2ddesc.add_adapters); } return base.GetEditor(editorBaseType); } public override TypeConverter Converter { get { if (IsReadOnly) return null; if (type_converters.Length > 0) { return base.Converter; } foreach (IG2DPropertyAdapter adapter in g2ddesc.adapter_list) { TypeConverter converter = adapter.GetConverter(field, DecleardFieldType, componentData); if (converter != null) { return converter; } } if (expandables.Length > 0) { return new G2DUIFieldExpandableConverter(g2ddesc); } if (expandables_f.Length > 0) { return new G2DUIFieldExpandableConverter(g2ddesc); } if (IsNeedG2DCollectionEditor(fieldType)) { return new G2DUIFieldListConverter(g2ddesc); } return base.Converter; } } } public class FieldMemberDescriptor : MemberPropertyDescriptor { public FieldMemberDescriptor(G2DPropertyDescriptor g2ddesc, int index, FieldInfo field, object componentData, Attribute[] attributes) : base(g2ddesc, index, field, componentData, attributes) { } public override Type DecleardFieldType { get { return Field.FieldType; } } public override object GetValue(object component) { return field.GetValue(component); } public override void SetValue(object component, object value) { field.SetValue(component, value); } } public class PropertyMemberDescriptor : MemberPropertyDescriptor { protected readonly MethodInfo set_op; protected readonly MethodInfo get_op; public PropertyMemberDescriptor(G2DPropertyDescriptor g2ddesc, int index, PropertyInfo field, object componentData, Attribute[] attributes) : base(g2ddesc, index, field, componentData, attributes) { this.get_op = field.GetGetMethod(); this.set_op = field.GetSetMethod(); } public override bool IsReadOnly { get { if (set_op == null) return true; return base.IsReadOnly; } } public override Type DecleardFieldType { get { return Field.PropertyType; } } public override object GetValue(object component) { if (get_op != null) return get_op.Invoke(component, new object[] { }); return null; } public override void SetValue(object component, object value) { if (set_op != null) set_op.Invoke(component, new object[] { value }); } } //------------------------------------------------------------------ /* public class CustomPropertyDescriptor : PropertyDescriptor, IG2DPropertyDescriptor { public readonly int index; public readonly G2DPropertyDescriptor g2ddesc; private FieldInfo field; private Type fieldType; private object componentData; private Type componentType; private DescAttribute desc; private DependOnPropertyAttribute[] depends; private TypeConverterAttribute[] type_converters; private ExpandableAttribute[] expandables; private ExpandableAttribute[] expandables_f; private NotNullAttribute notNull; public CustomPropertyDescriptor( G2DPropertyDescriptor g2ddesc, int index, FieldInfo field, object componentData, Attribute[] attributes) : base(field.Name, attributes) { this.g2ddesc = g2ddesc; this.index = index; this.field = field; this.fieldType = field.FieldType; this.componentData = componentData; this.componentType = componentData.GetType(); this.desc = PropertyUtil.GetDesc(field); object fieldValue = field.GetValue(componentData); if (fieldValue != null) { fieldType = fieldValue.GetType(); } this.depends = (DependOnPropertyAttribute[])field.GetCustomAttributes(typeof(DependOnPropertyAttribute), false); this.type_converters = (TypeConverterAttribute[])fieldType.GetCustomAttributes(typeof(TypeConverterAttribute), true); this.expandables = (ExpandableAttribute[])fieldType.GetCustomAttributes(typeof(ExpandableAttribute), true); this.expandables_f = (ExpandableAttribute[])field.GetCustomAttributes(typeof(ExpandableAttribute), true); this.notNull = PropertyUtil.GetAttribute(field); } public object ComponentData { get { return componentData; } } public bool NotNull { get { return notNull != null; } } public Type DecleardFieldType { get { return field.FieldType; } } public object FieldValue { get { return field.GetValue(componentData); } } public override Type ComponentType { get { return componentType; } } public override bool IsReadOnly { get { if (depends != null && depends.Length > 0) { foreach (DependOnPropertyAttribute depend in depends) { bool expect = PropertyUtil.GetFieldOrPropertyOrMethodValue(componentData, depend.PropertyName); if (expect != depend.Expect) { return true; } } } return false; } } public override Type PropertyType { get { if (IsReadOnly) return typeof(string); return fieldType; } } public override string DisplayName { get { return base.DisplayName; } } public override string Description { get { StringBuilder sb = new StringBuilder(); if (desc != null) { sb.AppendLine(desc.Desc); } object fieldValue = field.GetValue(componentData); ToDescription(sb, fieldValue); sb.AppendLine(base.Description); return sb.ToString(); } } public override string Category { get { if (desc != null) { return desc.Category; } return base.Category; } } public override bool CanResetValue(object component) { return false; } public override void ResetValue(object component) { } public override object GetValue(object component) { return field.GetValue(component); } public override void SetValue(object component, object value) { field.SetValue(component, value); } public override bool ShouldSerializeValue(object component) { return false; } public override object GetEditor(Type editorBaseType) { if (IsReadOnly) return null; foreach (IG2DPropertyAdapter adapter in g2ddesc.adapter_list) { UITypeEditor editor = adapter.GetEditor(field, componentData); if (editor != null) { return editor; } } if (IsNeedG2DCollectionEditor(fieldType)) { return new G2DFieldMemberEditor(field, field.GetValue(componentData), true, g2ddesc.add_adapters); } else if (IsNeedG2DEditor(fieldType)) { return new G2DFieldMemberEditor(field, field.GetValue(componentData), false, g2ddesc.add_adapters); } return base.GetEditor(editorBaseType); } public override TypeConverter Converter { get { if (IsReadOnly) return null; if (type_converters.Length > 0) { return base.Converter; } foreach (IG2DPropertyAdapter adapter in g2ddesc.adapter_list) { TypeConverter converter = adapter.GetConverter(field, componentData); if (converter != null) { return converter; } } if (expandables.Length > 0) { return new G2DUIFieldExpandableConverter(g2ddesc); } if (expandables_f.Length > 0) { return new G2DUIFieldExpandableConverter(g2ddesc); } if (IsNeedG2DCollectionEditor(fieldType)) { return new G2DUIFieldListConverter(g2ddesc); } return base.Converter; } } } */ //------------------------------------------------------------------ public class EnumPropertyDescriptor : PropertyDescriptor { public readonly G2DPropertyDescriptor g2ddesc; private object componentData; private Type componentType; public EnumPropertyDescriptor( G2DPropertyDescriptor g2d, object componentData, Attribute[] attributes) : base("Value", attributes) { this.g2ddesc = g2d; this.componentData = componentData; this.componentType = componentData.GetType(); } public override Type ComponentType { get { return componentType; } } public override bool IsReadOnly { get { return false; } } public override Type PropertyType { get { return componentType; } } public override bool CanResetValue(object component) { return false; } public override object GetValue(object component) { return componentData; } public override void ResetValue(object component) { } public override void SetValue(object component, object value) { componentData = value; g2ddesc.EditData = value; } public override bool ShouldSerializeValue(object component) { return true; } } //------------------------------------------------------------------ public abstract class CollectionItemPropertyDescriptor : PropertyDescriptor, IG2DPropertyDescriptor { public int Index { get; private set; } public G2DPropertyDescriptor Descriptor { get; private set; } public object ListOwner { get; private set; } public object ComponentData { get { return ListOwner; } } public object FieldValue { get { return ElementItem; } } public abstract object ElementItem { get; } public abstract Type ElementType { get; } public CollectionItemPropertyDescriptor(G2DPropertyDescriptor g2ddesc, object listOwner, int index, Attribute[] attributes) : base(index.ToString(), attributes) { this.Descriptor = g2ddesc; this.Index = index; this.ListOwner = listOwner; } public abstract Type DecleardFieldType { get; } public override Type ComponentType { get { return ListOwner.GetType(); } } public bool NotNull { get { return false; } } public override bool IsReadOnly { get { return false; } } public override Type PropertyType { get { if (ElementItem != null) return ElementItem.GetType(); return ElementType; } } public override string Description { get { StringBuilder sb = new StringBuilder(); ToDescription(sb, ElementItem); sb.AppendLine(base.Description); return sb.ToString(); } } public override bool CanResetValue(object component) { return false; } public override void ResetValue(object component) { } public override bool ShouldSerializeValue(object component) { return false; } public override object GetEditor(Type editorBaseType) { if (IsNeedG2DEditor(PropertyType)) { return new G2DCollectionItemEditor(ElementItem, ElementType, Descriptor.add_adapters); } return base.GetEditor(editorBaseType); } public override TypeConverter Converter { get { if (PropertyType.GetCustomAttributes(typeof(ExpandableAttribute), true).Length > 0) { return new G2DUIFieldExpandableConverter(Descriptor); } return base.Converter; } } } //------------------------------------------------------------------ public class ListItemPropertyDescriptor : CollectionItemPropertyDescriptor { private readonly Type genericItemType; public override object ElementItem { get { return GetValue(ListOwner); } } public override Type ElementType { get { return genericItemType; } } public override Type DecleardFieldType { get { return genericItemType; } } public ListItemPropertyDescriptor(G2DPropertyDescriptor g2ddesc, IList listOwner, int index, Attribute[] attributes) : base(g2ddesc, listOwner, index, attributes) { Type listtype = listOwner.GetType(); if (listtype.IsGenericType) { this.genericItemType = listOwner.GetType().GetGenericArguments()[0]; } else { this.genericItemType = typeof(object); } } public override object GetValue(object component) { IList list = component as IList; if (Index >= 0 && Index < list.Count) { return list[Index]; } return null; } public override void SetValue(object component, object value) { IList list = component as IList; if (Index >= 0 && Index < list.Count) { list[Index] = value; } } } //------------------------------------------------------------------ public class ArrayItemPropertyDescriptor : CollectionItemPropertyDescriptor { private readonly Type genericItemType; public override object ElementItem { get { return GetValue(ListOwner); } } public override Type ElementType { get { return genericItemType; } } public override Type DecleardFieldType { get { return genericItemType; } } public ArrayItemPropertyDescriptor(G2DPropertyDescriptor g2ddesc, IList listOwner, int index, Attribute[] attributes) : base(g2ddesc, listOwner, index, attributes) { this.genericItemType = listOwner.GetType().GetElementType(); } public override object GetValue(object component) { Array list = component as Array; if (Index >= 0 && Index < list.Length) { return list.GetValue(Index); } return null; } public override void SetValue(object component, object value) { Array list = component as Array; if (Index >= 0 && Index < list.Length) { list.SetValue(value, Index); } } } //------------------------------------------------------------------ public class MapItemPropertyDescriptor : PropertyDescriptor, IG2DPropertyDescriptor { private readonly G2DPropertyDescriptor g2ddesc; private readonly IDictionary mapOwner; private readonly object key; private readonly Type[] genericArgs; public G2DPropertyDescriptor Descriptor { get { return g2ddesc; } } public IDictionary MapOwner { get { return mapOwner; } } public object ComponentData { get { return mapOwner; } } public Type DecleardFieldType { get { return genericArgs[1]; } } public object FieldValue { get { return GetValue(mapOwner); } } public bool NotNull { get { return true; } } public object Key { get { return key; } } public object Value { get { return GetValue(mapOwner); } } public override Type ComponentType { get { return MapOwner.GetType(); } } public override bool IsReadOnly { get { return false; } } public override Type PropertyType { get { var value = Value; if (value != null) return value.GetType(); return DecleardFieldType; } } public override string Description { get { StringBuilder sb = new StringBuilder(); ToDescription(sb, Value); sb.AppendLine(base.Description); return sb.ToString(); } } public MapItemPropertyDescriptor(G2DPropertyDescriptor g2ddesc, IDictionary mapOwner, object key, Attribute[] attributes) : base(key.ToString(), attributes) { this.g2ddesc = g2ddesc; this.key = key; this.mapOwner = mapOwner; this.genericArgs = mapOwner.GetType().GetGenericArguments(); } public override object GetValue(object component) { return mapOwner[key]; } public override void SetValue(object component, object value) { mapOwner[key] = value; } public override bool CanResetValue(object component) { return false; } public override void ResetValue(object component) { } public override bool ShouldSerializeValue(object component) { return false; } public override object GetEditor(Type editorBaseType) { var value = Value; var keyType = key.GetType(); var valueType = DecleardFieldType; if (value != null) { valueType = value.GetType(); } if (keyType.IsPrimitive || keyType == typeof(string)) { if (IsNeedG2DEditor(valueType)) { return new G2DCollectionItemEditor(value, valueType, Descriptor.add_adapters); } } return null; } public override TypeConverter Converter { get { if (PropertyType.GetCustomAttributes(typeof(ExpandableAttribute), true).Length > 0) { return new G2DUIFieldExpandableConverter(Descriptor); } return base.Converter; } } } } //-------------------------------------------------------------------------------------------------------------------------------- /// /// 内部DataAdapters /// public class InternalDataAdapters : IG2DPropertyAdapter { public UITypeEditor GetEditor(MemberInfo field, Type fieldType, object ownerData) { if (PropertyUtil.GetAttribute(field) != null && fieldType == typeof(string)) { return new G2DDirectoryDialogEditor(field, ownerData); } else if (PropertyUtil.GetAttribute(field) != null && fieldType == typeof(string)) { return new G2DFileDialogEditor(field, ownerData); } else if (PropertyUtil.GetAttribute(field) != null && fieldType == typeof(int)) { return new G2DColorEditor(field, ownerData); } else if (PropertyUtil.GetAttribute(field) != null && fieldType == typeof(string)) { return new G2DOptionalEditor(field, ownerData); } return null; } public TypeConverter GetConverter(MemberInfo field, Type fieldType, object ownerData) { if (PropertyUtil.GetAttribute(field) != null && fieldType == typeof(int)) { return new G2DIntToHexTypeConverter(); } return null; } } //-------------------------------------------------------------------------------------------------------------------------------- #region _TypeConverter_ public class G2DUIFieldListConverter : TypeConverter { private readonly G2DPropertyDescriptor g2ddesc; public G2DUIFieldListConverter(G2DPropertyDescriptor g2d) { g2ddesc = g2d; } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType.GetInterface(typeof(ICollection).FullName) != null) { return true; } if (destinationType.IsArray) { return true; } return false; } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (value is ICollection) { ICollection list = (ICollection)value; return "集合:[" + list.Count + "]"; } if (destinationType.IsArray) { StringBuilder sb = new StringBuilder(); sb.Append("数组:"); Array array = value as Array; int[] ranks = new int[array.Rank]; foreach (int len in ranks) { sb.Append("[" + len + "]"); } return sb.ToString(); } return base.ConvertTo(context, culture, value, destinationType); } public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return g2ddesc.ListPropertyDescriptors(value, g2ddesc, attributes); } public override bool GetPropertiesSupported(ITypeDescriptorContext context) { return true; } } //-------------------------------------------------------------------------------------- public class G2DUIFieldExpandableConverter : ExpandableObjectConverter { private readonly G2DPropertyDescriptor g2ddesc; public G2DUIFieldExpandableConverter(G2DPropertyDescriptor g2d) { g2ddesc = g2d; } public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return g2ddesc.ListPropertyDescriptors(value, g2ddesc, attributes); } public override bool GetPropertiesSupported(ITypeDescriptorContext context) { return true; } } // -------------------------------------------------------------------------------------- public class G2DIntToHexTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) { return true; } else { return base.CanConvertFrom(context, sourceType); } } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(string)) { return true; } else { return base.CanConvertTo(context, destinationType); } } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string) && value.GetType() == typeof(int)) { return string.Format("0x{0:X8}", value); } else { return base.ConvertTo(context, culture, value, destinationType); } } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value.GetType() == typeof(string)) { string input = (string)value; if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { input = input.Substring(2); } return int.Parse(input, NumberStyles.HexNumber, culture); } else { return base.ConvertFrom(context, culture, value); } } } //-------------------------------------------------------------------------------------- #endregion //-------------------------------------------------------------------------------------------------------------------------------- #region _UITypeEditor_ public class G2DFieldMemberEditor : UITypeEditor { private readonly MemberInfo fieldInfo; private readonly Type fieldType; private readonly IG2DPropertyAdapter[] adapters; private object fieldValue; private readonly ListAttribute listDesc; private readonly NotNullAttribute notNull; private readonly bool isList; public G2DFieldMemberEditor(MemberInfo field, object fieldValue, bool isList, IG2DPropertyAdapter[] adapters) { this.isList = isList; this.fieldInfo = field; if (field is FieldInfo) { this.fieldType = (field as FieldInfo).FieldType; } else if (field is PropertyInfo) { this.fieldType = (field as PropertyInfo).PropertyType; } this.fieldValue = fieldValue; this.adapters = adapters; if (this.fieldValue != null) { fieldType = fieldValue.GetType(); } this.listDesc = PropertyUtil.GetListDesc(field); this.notNull = PropertyUtil.GetAttribute(field); } /// /// 编辑属性值时,在右侧显示...更多按钮 /// /// /// public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { if (fieldType.IsPrimitive) { return UITypeEditorEditStyle.None; } else if (fieldType.IsEnum) { return UITypeEditorEditStyle.None; } else if (fieldType.Equals(typeof(string))) { return UITypeEditorEditStyle.None; } else if (fieldType.IsClass) { return UITypeEditorEditStyle.Modal; } else if (fieldType.IsArray) { return UITypeEditorEditStyle.Modal; } return UITypeEditorEditStyle.Modal; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { var edSvc = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService; if (edSvc != null) { if (isList) { if(listDesc != null && listDesc.ElementTypes != null) { var list = listDesc.ElementTypes.ToArray(); if(list != null && list.Length > 0) { G2DCollectionEditor editor = new G2DCollectionEditor( fieldType, value, list, adapters); if (editor.ShowDialog() == System.Windows.Forms.DialogResult.OK) { value = editor.GetEditCompleteData(); } return value; } } MessageBox.Show($"标识为列表的属性打开出错({fieldType}), 忘记标识ListAttribute?"); } else { G2DFieldEditor editor = new G2DFieldEditor(fieldType, value, (notNull == null), adapters); if (editor.ShowDialog() == DialogResult.OK) { value = editor.EditObject; } } return value; } return base.EditValue(context, provider, value); } } public class G2DCollectionItemEditor : UITypeEditor { public object ElementItem { get; private set; } public Type ElementType { get; private set; } private IG2DPropertyAdapter[] adapters; public G2DCollectionItemEditor(object fieldValue, Type fieldType, IG2DPropertyAdapter[] adapters) { this.ElementItem = fieldValue; this.ElementType = fieldType; this.adapters = adapters; } /// /// 编辑属性值时,在右侧显示...更多按钮 /// /// /// public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { if (ElementType.IsPrimitive) { return UITypeEditorEditStyle.None; } else if (ElementType.IsEnum) { return UITypeEditorEditStyle.None; } else if (ElementType.Equals(typeof(string))) { return UITypeEditorEditStyle.None; } else if (ElementType.IsClass) { return UITypeEditorEditStyle.Modal; } else if (ElementType.IsArray) { return UITypeEditorEditStyle.Modal; } return UITypeEditorEditStyle.Modal; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { var edSvc = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService; if (edSvc != null) { G2DFieldEditor editor = new G2DFieldEditor(ElementType, value, false, adapters); if (editor.ShowDialog() == DialogResult.OK) { value = editor.EditObject; } return value; } return base.EditValue(context, provider, value); } } //-------------------------------------------------------------------------------------------------------------------------------- public abstract class G2DMemberUITypeEditor : UITypeEditor { protected readonly MemberInfo fieldInfo; protected readonly Type fieldType; protected readonly DescAttribute desc; protected readonly object ownerData; public G2DMemberUITypeEditor(MemberInfo field, object ownerData) { this.desc = PropertyUtil.GetAttribute(field); this.fieldInfo = field; this.ownerData = ownerData; if (fieldInfo is FieldInfo) { fieldType = (fieldInfo as FieldInfo).FieldType; } else if (fieldInfo is PropertyInfo) { fieldType = (fieldInfo as PropertyInfo).PropertyType; } else { fieldType = null; } } public object GetOwnerValue() { return PropertyUtil.GetMemberValue(fieldInfo, ownerData); } public void SetOwnerValue(object value) { PropertyUtil.SetMemberValue(fieldInfo, ownerData, value); } } public class G2DDirectoryDialogEditor : G2DMemberUITypeEditor { public G2DDirectoryDialogEditor(MemberInfo field, object ownerData) : base(field, ownerData) { } public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { string path = (string)base.GetOwnerValue(); { FolderBrowserDialog fd = new FolderBrowserDialog(); fd.SelectedPath = path; if (fd.ShowDialog() == DialogResult.OK) { return fd.SelectedPath; } } return base.EditValue(context, provider, value); } } public class G2DFileDialogEditor : G2DMemberUITypeEditor { public G2DFileDialogEditor(MemberInfo field, object ownerData) : base(field, ownerData) { } public override bool GetPaintValueSupported(ITypeDescriptorContext context) { return true; } public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { string path = (string)base.GetOwnerValue(); { OpenFileDialog fd = new OpenFileDialog(); fd.InitialDirectory = path; if (fd.ShowDialog() == DialogResult.OK) { return fd.FileName; } } return base.EditValue(context, provider, value); } } public class G2DColorEditor : G2DMemberUITypeEditor { private SolidBrush brush = new SolidBrush(Color.Green); public G2DColorEditor(MemberInfo field, object ownerData) : base(field, ownerData) { } public override bool GetPaintValueSupported(ITypeDescriptorContext context) { return true; } public override void PaintValue(PaintValueEventArgs e) { int color = (int)base.GetOwnerValue(); brush.Color = Color.FromArgb(color); e.Graphics.FillRectangle(brush, e.Bounds); } public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { int color = (int)base.GetOwnerValue(); { ColorDialog cd = new ColorDialog(); cd.Color = Color.FromArgb(color); if (cd.ShowDialog() == DialogResult.OK) { return cd.Color.ToArgb(); } } return base.EditValue(context, provider, value); } } public class G2DOptionalEditor : G2DMemberUITypeEditor { private OptionalValueAttribute optional; public G2DOptionalEditor(MemberInfo field, object ownerData) : base(field, ownerData) { this.optional = PropertyUtil.GetAttribute(fieldInfo); } public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.DropDown; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { IWindowsFormsEditorService wfes = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService; if (wfes != null) { var list = new ListBox(); foreach (var o in optional.Values) { list.Items.Add(o); } list.SelectedValueChanged += (s, e) => { wfes.CloseDropDown(); }; wfes.DropDownControl(list); if (list.SelectedItems.Count > 0) { value = list.SelectedItem.ToString(); } list.Dispose(); } return value; } } #endregion //-------------------------------------------------------------------------------------------------------------------------------- }