如何定制.NET类型转换器简介
当在设计平面上选中某个组件,你选中的就是这个组件的某个实例,显示在属性浏览器里的书形象都是来自这个实例。当在属性浏览器中对属性进行编辑时,新属性值也将被刷新到这个实例中。这很容易理解,但也往往不那么直观,因为属性浏览器只能把属性(不管是什么类型)显示为文本。在属性值在属性浏览器和那个组件实例见来回传递时,他们必须在字符串和他们真实的类型之间来回传递。
既然要进行类型转换,就需要有类型转换器(type converter),他们在.NET中主要用途就是对各种类型进行转换。.NET已经为程序员准备了内建的类型转换器,但如果你的组件或控件包含一些基于定制类型的属性――比如那个时钟控件ClockControl(源代码见《.Net窗体设计阶段的功能集成问答》 )的HourHand,MinuteHand,SecongHand属性,他们就无能为力了:
1

public class Hand
{2
private Color color = Color.Black;3
private int width = 1;4

public Hand(Color color, int width)
{5
this.color = color;6
this.width = width;7
}8

9

public Color Color
{10

get
{ return color; }11

set
{ color = value; }12
}13

14

public int Width
{15

get
{ return width; }16

set
{ width = value; }17
}18
}
如果没有定制的类型转换器,你只能看到如下图所示画面:
创建定制的类型转换器:
1.从TypeConverter基类派生一个新类HandConverter。
2.为了支持类型转换,HandConverter类必须对CanConvertFrom,ConvertTo和ConvertFrom方法进行覆盖。
3.为了让多值属性和嵌套属性具备展开编辑功能,可将基类改为ExpandableObjectConverter。对比效果如下图:

4.对GetCreateInstanceSupported和CreateInstance方法进行覆盖,使得当在属性浏览器里编辑嵌套属性时能立即刷新根属性。(比如你修改HourHand.Color属性,HourHand属性会立刻更新。)
1

public class HandConverter : ExpandableObjectConverter
{2
// Don't need to override CanConvertTo if converting to string, as that's what base TypeConverter does3
// Do need to override CanConvertFrom since it's base converts from InstanceDescriptor4

5

public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{6
// We can be converted to an InstanceDescriptor7
if( destinationType == typeof(InstanceDescriptor) ) return true;8
return base.CanConvertTo(context, destinationType);9
}10
11

public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{12
// We can convert from a string to a Hand type13

if( sourceType == typeof(string) )
{ return true; }14
return base.CanConvertFrom(context, sourceType);15
}16

17

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo info, object value)
{18

19
// If converting from a string20

if( value is string )
{21
// Build a Hand type 22

try
{23
// Get Hand properties24
string propertyList = (string)value;25
string[] properties = propertyList.Split(';');26
return new Hand(Color.FromName(properties[0].Trim()), 27
Convert.ToInt32(properties[1]));28
}29

catch
{}30
throw new ArgumentException("The arguments were not valid.");31
}32
return base.ConvertFrom(context, info, value);33
}34
35

public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{36

37
// If source value is a Hand type38

if( value is Hand )
{39
// Convert to string40

if( (destinationType == typeof(string)) )
{41
Hand hand = (Hand)value;42
string color = (hand.Color.IsNamedColor ? 43
hand.Color.Name : 44
hand.Color.R + ", " + hand.Color.G + ", " + hand.Color.B);45
return string.Format("{0}; {1}", color, hand.Width.ToString());46
}47
// Convert to InstanceDescriptor48

if( (destinationType == typeof(InstanceDescriptor)) )
{49
Hand hand = (Hand)value;50
object[] properties = new object[2];51
Type[] types = new Type[2];52

53
// Color54
types[0] = typeof(Color);55
properties[0] = hand.Color;56

57
// Width58
types[1] = typeof(int);59
properties[1] = hand.Width;60

61
// Build constructor62
ConstructorInfo ci = typeof(Hand).GetConstructor(types);63
return new InstanceDescriptor(ci, properties);64
}65
} 66
// Base ConvertTo if neither string or InstanceDescriptor required67
 
- 上一篇:VS2008中vss的设置
- 下一篇:实例应用.NET MSchart图表工具

