前面的幾篇文章中,我們給控件添加一個復雜的類型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是如下的形式:
