设置控件属性
最简单直接设置属性的方法是使用特性(attribute)句法.但是,在某些情况,只能用元素(element)句法.
特性句法
大部分的属性可以使用特性句法以一个简单的字符串形式表现.在XAML设置一个特性就好像是在XML里设置一个特性.一个XML元素包含一个节点和一些特性.Silverlight控件以相同的方式定义,控件名是节点,属性以特性(attributes)的方式定义.
例如,你可以简单地使用特性句法设置一个按钮控件的Width,Height和Content属性,如下:
<Button Width="100" Height="30" Content="Bottom Right"></Button>
元素句法
元素句法是当属性值不能用特性句法的简单的字符串表达时使用.还有,它与XML中的元素非常相似.下面的例子展示给一个按钮添加背景元素:
<Button Width="100" Height="30" Content="Click Me!"> <Button.Background> <SolidColorBrush Color="Blue"/> </Button.Background> <Button.Foreground> <SolidColorBrush Color="Red"/> </Button.Foreground> </Button>
可类型转换特性(Type-Converter-Enabled Attributes)
某些时候,当通过特性定义属性时,属性值不能用简单的字符串表达,它会转换为一个复合的类型.一个简单的可类型转换特性的例子就是Margin.这个Margin属性可以可以被设为一个简单的字符串,例如:
<Button Width="100" Height="30" Content="Click Me!" Margin="15"/>
当你以这样的形式设置Margin属性时,左,右,上和下的Margin都会设为15px.如果你只想设置上Margin为15px,其它为0,怎么办呢?如下:
<Button Width="100" Height="30" Content="Click Me!" Margin="0,15,0,0"/>这里Silverlight会取出字符串"0,15,0,0"同时把它转换为一个复合的类型.这个字符串会转换为4个值:left margin = 0, top margin = 15, right margin = 0, 和bottom margin = 0.
附属属性
在上一篇文章,你学习了怎样使用附属属性设置一个控件在Canvas里的位置.一个附属属性是一个附属于父控件的属性.在上一篇文章的例子里,你通过设置两个属性指定按钮控件在Canvas对象里的位置:Canvas.Top和Canvas.Left.这两个属性附属于按钮控件的父控件Canvas.
<Button Width="100" Height="30" Content="Button 2" Canvas.Left="10" Canvas.Top="40" />
控件嵌套控件
当你第一次看到Silverlight2包含的控件时,你可能感到份外亲切,它们看起来就像期望的那样.但是当你仔细研究控件的特性,你会发现控件比你看它的第一眼的感觉要复杂得多.
Silverlight 2的一个最关键的特性是可以放任何东西到一个控件里.一个按钮控件可以包含一个StackPanel,这个StackPanel又可以包含一个Ellipse和一个TextBlock.一个控件的内容(Contents)可以是什么有一些限制.下面展示一个标准的Silverlight 2按钮包含一个StackPanel,一个嵌套的StackPanel,一个Ellipse,一个TextBlock,和一个ListBox.
<Button Height="180" Width="200"> <StackPanel Orientation="Vertical"> <StackPanel Margin="5" VerticalAlignment="Center" Orientation="Horizontal"> <Ellipse Fill="Yellow" Width="25" /> <TextBlock VerticalAlignment="Center" Margin="5" Text="Check Forecast" /> </StackPanel> <ListBox FontSize="11" Opacity="0.5" Margin="2" x:Name="lstForecastGlance"> <ListBoxItem> <TextBlock VerticalAlignment="Center" Text="Mon: Sunny (85)" /> </ListBoxItem> <ListBoxItem> <TextBlock VerticalAlignment="Center" Text="Tue: Partly Cloudy (89)" /> </ListBoxItem> <ListBoxItem> <TextBlock VerticalAlignment="Center" Text="Wed: Thunderstorms (78)" /> </ListBoxItem> <ListBoxItem> <TextBlock VerticalAlignment="Center" Text="Thu: Thunderstorms (76)" /> </ListBoxItem> <ListBoxItem> <TextBlock VerticalAlignment="Center" Text="Fri: Partly Cloudy (71)" /> </ListBoxItem> <ListBoxItem> <TextBlock VerticalAlignment="Center" Text="Sat: Mostly Sunny (74)" /> </ListBoxItem> <ListBoxItem> <TextBlock VerticalAlignment="Center" Text="Sun: Sunny (80)" /> </ListBoxItem> </ListBox> </StackPanel> </Button>
正如代码所示,这个例子简单地嵌套一些内容到一个按钮里.正如你所想的,这是一个非常强大的特性.
在Silverlight里处理事件
在为另一个Microsoft的编程框架,Silverlight提供一个事件机制来跟踪发生在应用程序里的actions.两类的actions会被跟踪:
- 基于一些来自用户的输入而被触发的actions.输入actions会被处理和会从浏览器到Silverlight对象模型向上"冒泡".
- 基于一个特定的对象的状态变化而触发的actions,包括在应用程序里的对象的状态.这些actions会从Silverlight对象模型里立即处理.
事件处理程序是一些当被触发时立即运行的方法.你即可以通过XAML标记本身定义,也可以在托管代码里定义.下面的练习会显示展示两种方式定义事件处理程序.
在XAML里声明事件
- 使用VS2010创建一个名为EventHandlers的Silverlight应用程序.
- 为根表格添加4行,2列.
- 接着,添加一个按钮到左上单元格,一个TextBlock到右上单元格.
- 为这个按钮添加一个Click属性.当你输入到"Click="时,VS会自动提示一个选项来添加一个新的事件处理程序.如下所示.当<新建事件处理程序>选择出现事,按下Enter键,VS就会完成Click属性.
代码如下:
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition Height="70" /> <RowDefinition Height="70" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="150"/> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Button Width="125" Height="35" Content="XAML Event" Click="Button_Click"/> <TextBlock Text="Click the XAML Event!" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Grid>
另外,VS会自动为Silverlight应用程序添加一个名为Button_Click的事件处理程序到后置代码类里,如下:
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { } }
- 在这个例子里,你会改变TextBlock的Text属性.为了做到这点,你首先要给TextBlock一个name属性,如下:
<TextBlock Name="txtXAMLEventText" Text="Click the XAML Event!" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" />
- 现在在Button_Click事件里改变TextBlock控件的Text属性:
private void Button_Click(object sender, RoutedEventArgs e) { txtXAMLEventText.Text = "现在的时间是:" + DateTime.Now.ToString(); }
- 运行程序,点击按钮.会显示当前的时间.如下:
通过托管代码声明事件处理程序
继续在这个项目里练习.
- 添加一个按钮到根表格控件的第二行.
- 要在托管代码里引用新的按钮和TextBlock,你就必须给他们一个name属性,如下:
<Button Name="btnManaged" Width="125" Height="35" Content="Managed Event" Grid.Row="1" />
<TextBlock Name="txtManagedEventText" Text="Click the Managed Event!" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="1" /> - 接着,右击页面,选择"查看代码".这会转换到后置代码页面.
到这里,你会使用标准的CLR语言来添加事件处理程序.因为你使用的是C#,语法是使用"+="操作符,给它分配一个新的EventHandler.VS会帮助你完成这些.完成后代码如下:
public MainPage() { InitializeComponent(); this.btnManaged.Click += new RoutedEventHandler(btnManaged_Click); } static int i = 0; void btnManaged_Click(object sender, RoutedEventArgs e) { this.txtManagedEventText.Text = i.ToString(); i++; }
- 运行代码,结果如下:
这个练习显示了怎么使用C#和托管代码定义事件处理程序.
在剩下的部分,我们浏览一遍Silverlight较为常用的表单控件.
Border控件
Border控件为Silverlight的任何一个控件提供一个方法来添加一条边线和背景.尽管每个控件多会有一个Border,你也总是可以放置一个Border到一个StackPanel里,或者放到一个Grid里,结果就是多了一个Border.
添加一个Border到你的Silverlight应用程序是非常简单的,看下面的例子:
<Grid x:Name="LayoutRoot" Background="White"> <Border BorderThickness="2" BorderBrush="Black" Margin="10"> <StackPanel Margin="10"> <Button Content="Sample Button" Margin="5" /> <TextBlock Text="Sample TextBlock" Margin="5" /> <ListBox Margin="5"> <ListBoxItem> <TextBlock Text="ListItem 1" /> </ListBoxItem> <ListBoxItem> <TextBlock Text="ListItem 2" /> </ListBoxItem> <ListBoxItem> <TextBlock Text="ListItem 3" /> </ListBoxItem> <ListBoxItem> <TextBlock Text="ListItem 4" /> </ListBoxItem> </ListBox> </StackPanel> </Border> </Grid>
效果如图:
Border控件的另一个特性是能使用CornerRadius属性做出圆角效果:
<Border BorderThickness="2" BorderBrush="Black" Margin="10" CornerRadius="10">
效果如图:
你可以使用Background属性定义背景颜色.就像BorderBrush属性,Background属性可以设为一个颜色,可以设为一个brush类.下面是使用Brush对象设置Border的Background的例子:
<Border BorderThickness="2" Margin="10" CornerRadius="10"> <Border.Background> <LinearGradientBrush> <LinearGradientBrush.GradientStops> <GradientStop Color="Green" Offset="0" /> <GradientStop Color="White" Offset="1" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Border.Background> <Border.BorderBrush> <LinearGradientBrush> <LinearGradientBrush.GradientStops> <GradientStop Color="Black" Offset="0" /> <GradientStop Color="White" Offset="1" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Border.BorderBrush> <StackPanel Margin="10"> <Button Content="Sample Button" Margin="5" /> <TextBlock Text="Sample TextBlock" Margin="5" /> <ListBox Margin="5"> <ListBoxItem> <TextBlock Text="ListItem 1" /> </ListBoxItem> <ListBoxItem> <TextBlock Text="ListItem 2" /> </ListBoxItem> <ListBoxItem> <TextBlock Text="ListItem 3" /> </ListBoxItem> <ListBoxItem> <TextBlock Text="ListItem 4" /> </ListBoxItem> </ListBox> </StackPanel> </Border>
效果如下:
扩展控件
-当一个Silverlight应用程序被部署时,它会打包为一个.xap文件.这个文件需要被每个客户端下载才能访问这个Silverlight应用程序.
Silverlight程序的一个优点是.xap文件的size总是很小的.其中一个原因是大部分的用户控件已包含在Silverlight运行时里.
然而,Silverlight在普通控件集合的基础上提供了一些控件.这些控件分别在两个程序集里:System.Windows.Controls.dll和System.Windows.Controls.Data.dll.只有开发者使用了这些程序集的控件时,这些DLLs会被包含进.xap文件.
添加一个扩展控件
当开发者使用其它控件类库的控件时,要在UserControl定义里添加一个xmlns声明.这个xmlns会有一个关联的前缀用于在后面引用那些特别的控件.例如,如果你在VS里为你的Silverlight应用程序里添加一个DataGrid控件,源码会像如下所示:
<UserControl x:Class="SilverlightApplication1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <Grid x:Name="LayoutRoot" Background="White"> <sdk:DataGrid AutoGenerateColumns="False" Name="dataGrid1" /> </Grid> </UserControl>
试试看:使用GridSplitter
一个在 System.Windows.Controls程序集里的控件是GridSplitter.这个控件提供用户可在应用程序里改变行或列宽度的能力.如果使用属性,GridSplitter会极大地改进你的应用程序的外观和用户体验.接下来的练习,你会实现一个简单的GridSplitter.
- 使用VS2010创建一个名为GridSplitterControl的Silverlight应用程序.
- 在根表格控件里定义2列.第一列150px宽,第二列暂满剩余空间.设置ShowGridLines为True.添加两个TextBlock控件,一个在第一列,一个在第二列,源码如下:
<Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="150" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBlock Text="Apress, Inc." /> <TextBlock Grid.Column="1" Text="Beginning Silverlight 4: From Novice to Professional" /> </Grid>
效果如图:
注意你不能看到第二列所有的文本. - 双击VS工具箱的GridSplitter添加控件,,到页面的设计视图里右击GridSplitter控件选择"重置布局"=>"全部"
<sdk:GridSplitter Background="LightGray" Name="gridSplitter1" />
- 运行程序,效果如下: