WPF,Silverlight与XAML读书笔记第四 - XAML元素子元素/内容及其模式
2009-08-28 15:45
441 查看
说明:本系列基本上是《WPF揭秘》的读书笔记。在结构安排与文章内容上参照《WPF揭秘》的编排,对内容进行了总结并加入一些个人理解。
XAML中子内容的处理由其父对象来决定,这就需要父元素类型实现System.Windows.Serialization命名空间的IAddChild接口或是实现标准的集合接口 – Icollection。如果试图添加子元素到一个没有实现这两种接口的元素类型,编译器将会报错。
XAML中元素处理其子元素/内容基本上就是以这两种通用的模式来完成,实现这个处理功能不是由XAML来完成的,而是由于父元素实现了.NET类库中两个接口才得以实现。
IAddChild接口定义了两个方法:AddChild和AddText,AddChild用来添加元素,AddText用来添加普通文本。编译器为每段子内容调用这两个方法。
示例代码:
XAML:
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> </Grid> </Window> |
Window1 myWindow = new Window1(); myWindow.AddChild(new Grid()); |
示例代码:(与前文代码等效,加入了粗体部分来演示内容属性的本质,语法上来看和属性元素一样)
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Window.Content> <Grid> </Grid> </Window.Content> </Window> |
Window1 myWindow = new Window1(); myWindow.Content = new Grid(); |
XAML中,一个对象元素可以有3种类型的子元素:
1. 内容属性值
2. 集合项
3. 能够通过类型转换到它的父元素的值。
下文将分别详细介绍。
1. 内容属性
WPF中很多类指定了一个属性,通过设置该属性的值可以给此类的元素来设置内容,这个特性称为内容属性。在某些情况下内容属性是比属性元素更简单的表示方法。将属性作为内容属性的方法是使用System.Windows.Markup.ContentPropertyAttribute标记这个属性。
对比下面两组例子:
第一:普通方式(以Xml Attribute方式)设置属性的方式改写为内容属性的表示方式:
XML Attribute:
<Button Content="OK"/> |
<Button>OK</Button> |
属性元素:
<Button> <Button.Content> <Rectangle Height="40" Width="40" Fill="Black"/> </Button.Content> </Button> |
<Button> <Rectangle Height="40" Width="40" Fill="Black"/> </Button> |
注意像Button、Window等从ContentControl继承的元素都只能包含一个单独的子元素,根本原因在于它们的子元素被作为内容属性(Content属性),而只能给Content属性指定一个值。当添加的元素超过一个会抛出异常。
另外,WPF中继承自Panel基类的布局容器将Children属性作为内容属性,所以有如下写法。(Children属性不像Content属性那样被限制只能指定一个值)
属性元素写法:
<StackPanel> <StackPanel.Children> <Button>Foo</Button> <Button>Bar</Button> </StackPanel.Children> </StackPanel> |
<StackPanel> <Button>Foo</Button> <Button>Bar</Button> </StackPanel> |
有一些类使用相同的方式表现子项的集合。如:XAML中两种类型的集合 - List与Dictionary支持向其中添加项。
List
Itmes集合
List指实现了System.Collection.IList接口的集合,如System.Collections.ArrayList类及WPF中定义的ListBox控件,RadioButtonList控件,ComboBox控件及TabControl控件。当添加一个子项到这些元素时,IAddChild接口就会将子项添加到Items集合中。
一般来说,设置它们的Items属性可以使用属性元素。如下示例:
向ListBox中添加两项:
<ListBox> <ListBox.Items> <ListBoxItem Content="Item1"/> <ListBoxItem Content="Item2"/> </ListBox.Items> </ListBox> |
<ListBox> <ListBoxItem Content="Item1"/> <ListBoxItem Content="Item2"/> </ListBox> |
Dictionary
Dictionary指的是实现了System.Collections.IDictionary接口的集合。下面以WPF中一个常用的集合类型System.Windows.ResourceDictionary为例,来演示使用XAML向Dictionary中添加键值对的方式,以下代码直接给出内容属性的写法(粗体部分):
<Grid> <Grid.Resources> <ResourceDictionary> <Color x:Key="1" A="255" R="255" G="255" B="255"/> <Color x:Key="2" A="0" R="0" G="0" B="0"/> </ResourceDictionary> </Grid.Resources> </Grid> |
下面是上面XAML等价的C#代码:
System.Windows.ResourceDictionary d = new ResourceDictionary(); System.Windows.Media.Color color1 = new Color(); System.Windows.Media.Color color2 = new Color(); color1.A = 255; color1.R = 255; color1.G = 255; color1.B = 255; color2.A = 0; color2.R = 0; color2.G = 0; color2.B = 0; d.Add("1", color1); d.Add("2", color2); |
当一个属性是集合类型(实现ICollection接口)时,通常不需要为集合自身再提供一个元素,而是让属性名来控制集合,通常用于只有一个属性的元素。(如下示例中,加粗代码表示的是不用再提供的元素)
注:例子使用属性元素,这样使示例代码的来龙去脉更清晰。(属性元素加虚下划线,去掉即是子内容的表示方式)
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <LinearGradientBrush.GradientStops> <GradientStopCollection> <GradientStop Color="Black" Offset="0" /> <GradientStop Color="Red" Offset="1" /> </GradientStopCollection> </LinearGradientBrush.GradientStops> </LinearGradientBrush> |
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <GradientStop Color="Black" Offset="0" /> <GradientStop Color="Red" Offset="1" /> </LinearGradientBrush> |
3. 支持类型转化的普通文本
首先看一下下面这个XAML中声明的SolidColorBrush:
<SolidColorBrush>White</SolidColorBrush> |
<SolidColorBrush Color="White"/> |
<Brush>White</Brush> |
下表总结了XAML中元素的子元素的处理规则:
当转换子元素时,任何一个有效的XAML分析器必须遵循下面的规则: (1) 如果该类型实现了ILits接口,就为每个子元素调用IList.Add。 (2) 否则,如果该类型实现了IDictionary,就为每个子元素调用IDictionary.Add,在该值的键和元素中使用x:Key特性值。 (3) 否则,如果父元素支持内容属性,而且子元素的类型与该内容属性是兼容的,就把子元素作为内容属性的值。 (4) 否则,如果子对象是普通文本,且有类型转换器将子对象转换为父元素的类型,则把子元素作为类型转换器的输入,将输出作为父元素的实例(没有在父元素上设置属性,子元素只相当于初始化父元素的一个参数)。 (5) 其他情况下,则抛出一个异常。 |
《WPF揭秘》
相关文章推荐
- WPF,Silverlight与XAML读书笔记第二十一 - 控件之三 – 内容控件之选择控件&信息显示控件
- WPF,Silverlight与XAML读书笔记第二十 - 控件之二 – 内容控件(命令控件)
- WPF,Silverlight与XAML读书笔记第三十三 - 可视化效果之布局内容溢出处理
- WPF,Silverlight与XAML读书笔记第二十二 - 控件之四 – 内容控件之带头的容器控件
- [分享]一些在 WPF/Silverlight 中应用 MVVM 模式时可能会有点用途的代码
- WPF,Silverlight与XAML读书笔记第二十八 - 控件之十 – 媒体控件
- WPF,Silverlight与XAML读书笔记第四十八 - Silverlight网络与通讯
- Silverlight/wpf DataGrid TextBox 等控件内容 Binding 中日期格式 StringFormat
- WPF,Silverlight与XAML读书笔记第十六 - 资源之二进制资源
- WPF,Silverlight与XAML读书笔记第十四 - 独立存储&部署
- WPF and Silverlight 学习笔记(十一):WPF控件内容模型
- WPF,Silverlight与XAML读书笔记第八 - WPF新概念之三路由事件
- WPF,Silverlight与XAML读书笔记第四十五 - 外观效果之模板
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十六) 牵引式地图移动模式②
- WPF,Silverlight与XAML读书笔记第二十四 - 控件之六 – Items控件之菜单&其它
- Silverlight/wpf DataGrid TextBox 等控件内容 Binding 中日期格式 StringFormat
- WPF,Silverlight与XAML读书笔记第四十 - 可视化效果之动画
- WPF and Silverlight 学习笔记(十二):WPF Panel内容模型、Decorator内容模型及其他
- Silverlight/WPF/Windows Phone 开发之MVVM设计模式之入门
- WPF/Silverlight陷阱:XAML自定义控件的嵌套内容无法通过名称访问