属性( Property )元素
WPF 的一大特色就是支持丰富的组合,下面的例子创建了一个中间是一个方块的按钮(按钮的标题已经不仅仅 是文本了):
System.Windows.Controls. Button b = new System.Windows.Controls. Button ();
System.Windows.Shapes. Rectangle r = new System.Windows.Shapes. Rectangle ();
r.Width = 40;
r.Height = 40;
r.Fill = System.Windows.Media. Brushes .Black;
b.Content = r; // 将按钮的内容设置为方块
按钮的 Content 属性是 System.Object 类型的,因此可以放置这个方块。通过代码我们可以非常轻松地设置按钮的内容,但是我们应该如何通过 XAML 来实现相同的工作呢?我们可以给 Content 属性 设置什么字符串值才能够使之与前面的 C# 代码等价呢?实际上,并不存在这样的字符 串值。不过 WPF 提供了另一种设置这种复杂属性值的语法:属性元素( property element ),如:
< Button xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation " >
< Button.Content >
< Rectangle Height = " 40 " Width = " 40 " Fill = " Black " />
</ Button.Content >
</ Button >
现在 Button 的 Content 属性是 XML 元素而不是 XML 属性,这段 XAML 代码与前面的 C# 代码等价。属性元素的形式总是 TypeName.PropertyName ,它们总是包含在 TypeName 对象 元素之中,且它们不能包含自己的 XML 属性。
属性元素也可以用于简单属性,如下两段 XAML 代 码完全等价:
<
Button
xmlns
="
http://schemas.microsoft.com/winfx/2006/xaml/presentation
"
Content
="
OK
"
Background
="
White
" />
<
Button
xmlns
="
http://schemas.microsoft.com/winfx/2006/xaml/presentation
">
<
Button.Content
>OK</
Button.Content
>
<
Button.Background
>
White
</
Button.Background
>
</ Button >
类型转换器
上面例子的等价 C# 代码如下:
System.Windows.Controls. Button b = new System.Windows.Controls. Button ();
b.Content = "OK" ;
b.Background = System.Windows.Media. Brushes .White;
注意到 XAML 中的 Background 属性,“ White ”字符串是如何与 System.Windows.Media.Brushes.White 等价的呢?这个用法展示了一种在 XAML 中使用字符串设置属性的方法。需要特别注意的是,需要被设置的属性的类型并非 System.String 或 System.Object 。在这种情况下, XAML 解析器 / 编译器必须去寻找类型转换器。类型转换器可 以把字符串转换成需要的数据类型。 WPF 为许多公共类型提供了类型转换器,如 Brush 等。它们都从 TypeConverter 派生(如 BrushConverter 等)。当然,我们也可以为自己的类型编写相应的类型转换器。与 XAML 不同,类型转换器的名称通常支持大小写不敏感的字符串。
如果 Brush 没有类型转换器,我们就必须使用属 性元素语法在 XAML 中设置 Background 属性了,如下:
< Button xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
Content = " OK " >
< Button.Background >
< SolidColorBrush Color = " White " />
</ Button.Background >
</ Button >
同样地,当 Color 属性没有类 型转换器的时候,我们必须如下编写 XAML 代码:
< Button xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
Content = " OK " >
< Button.Background >
< SolidColorBrush >
< SolidColorBrush.Color >
< Color A = " 255 " R = " 255 " G = " 255 " B = " 255 " />
</ SolidColorBrush.Color >
</ SolidColorBrush >
</ Button.Background >
</ Button >
上面的例子仍旧需要类型转换器来转换“ 255 ”( A 、 R 、 G 、 B 属性)到 Byte ,否则程序将不能继续。因此,类型 转换器不仅增强了 XAML 的可读性,而且使得上述概念得以实现,这是其他方式做不到的。
尽管 C# 代码可以产生与 XAML 相同的结果,但在程序代码当中,并非使用了相同的类型转换机制。下面的代码非常准确地展示了在运行时 返回并执行合适的类型转换器:
System.Windows.Controls. Button b = new System.Windows.Controls. Button ();
b.Content = "OK" ;
b.Background = ( Brush )System.ComponentModel. TypeDescriptor .GetConverter(
typeof ( Brush )).ConverterFromInvariantString( "White" );
注意:拼错“ White ”不会导致 编译错误(在 VS 中会有警告),但会导致运行时异常。