前面的幾篇文章中,我們給控件添加一個復雜的類型Scope,並且給它的類型提供的一個類型轉換器, 現在我們可以在屬性浏覽器中編輯它的值,並且它的值也被串行化的源代碼裡了。但是你有沒有發現,在 屬性浏覽器裡編輯這個屬性的值還是不太方便。因為屬性只是“10,200”這種形式的,所以,你必須按 照這種格式來修改,一旦格式錯誤就會引發異常,比如輸入一個“10200”。我們期望這個屬性的每一子 屬性都能夠被獨立的編輯就好了,這並非不能實現,而且實現還很簡單。
為了在屬性浏覽器裡能夠獨立的編輯子屬性,我們還要重寫兩個方法:GetPropertiesSupported() 和GetProperties();下面是ScopeConverter的完整代碼:
public class ScopeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(String)) return true; return base.CanConvertFrom(context, sourceType); } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(String)) return true; if (destinationType == typeof(InstanceDescriptor)) return true; return base.CanConvertTo(context, destinationType); } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { String result = ""; if (destinationType == typeof(String)) { Scope scope = (Scope)value; result = scope.Min.ToString()+"," + scope.Max.ToString(); return result; } if (destinationType == typeof(InstanceDescriptor)) { ConstructorInfo ci = typeof(Scope).GetConstructor(new Type[] {typeof(Int32),typeof(Int32) }); Scope scope = (Scope)value; return new InstanceDescriptor(ci, new object[] { scope.Min,scope.Max }); } return base.ConvertTo(context, culture, value, destinationType); } public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { if (value is string) { String[] v = ((String)value).Split(','); if (v.GetLength(0) != 2) { throw new ArgumentException("Invalid parameter format"); } Scope csf = new Scope(); csf.Min = Convert.ToInt32(v[0]); csf.Max = Convert.ToInt32(v[1]); return csf; } return base.ConvertFrom(context, culture, value); } public override bool GetPropertiesSupported(ITypeDescriptorContext context) { return true; } public override PropertyDescriptorCollection GetProperties (ITypeDescriptorContext context, object value, Attribute[] attributes) { return TypeDescriptor.GetProperties(typeof(Scope), attributes); } }
在GetProperties方法裡,我用TypeDescriptor獲得了Scope類的所有的屬性描述器並返回。如果你對 TypeDescriptor還不熟悉的話,可以參考MSDN。
重寫這兩個方法並編譯以後,在測試工程裡查看控件的屬性,你可以看到Scope是如下的形式: