Silverlight编程之Silverlight制作简易工具条控件(1)
下面使用Silverlight打造位运算器之制作简易工具条控件
位运算器在我的构思中需要有工具条按钮,就是按下去不会弹上来那种按钮。当年Delphi中有一个SpeedButton控件正好可以实现这样的功能。C#的WindowsApplication中可以使用RadioButton来实现这样的工具条。很遗憾,Silverlight中没有相关控件。但可以更改ListBox的模板来模拟这样的功能,这个我试验过,但由于ListBox存在Focus状态,ListItem在处于Focus状态时会有一个边框,看着很不顺眼,需要重写模板把这个状态去掉。定制RadioButton外观应该也能实现这样的功能(这点未做实验,有待验证)。但想来想去,为了学些新东西,还是自己实现一个工具条控件吧。经过一番努力,终于实现了这个工具条。本文将对制作的步骤进行详细讲解。
好,先来看看效果,这里需要注意,必须安装Silverlight 3.0版本才能正常运行示例。
关于控件制作,请先观看一篇写得非常棒的文章:
http://msdn.microsoft.com/zh-cn/magazine/cc721611.aspx
由于我的控件放在另一个项目之中,操作步骤会有所不同,所以这里有些地方我还得重新详细地介绍。
第一步,先做一个最简单的控件:
1、 首先创建一个Silverlight应用程序,项目命名为“BitCalculator”。
2、 在解决方案资源管理器的【解决方案“BitCalculator”】上单击鼠标右键,选中【添加】à【新建项目】添加一个【Silverlight类库】,命名为“BitLibrary”。
3、 将【BitLibrary】项目下的“Class1.cs”类改名为“SpeedButton.cs”。
4、 将SpeedButton.cs类的代码更改如下:
1 namespace BitLibrary
2 {
3 public class SpeedButton : ContentControl
4 {
5
6 }
7 }
8
这里,我们让SpeedButton类继续自ContentControl,道理很简单,Button类也是从ContentControl类继续的。很多的拥有Content属性的内置控件都继承自ContentControl类。我们记得,在C#中,Button使用的是Text属性,为什么在Silverlight中会改为Content属性呢?这是因为Content属性允许用户对按钮表面的内容进行自定义,如加一些图片或其他控件什么的,而所有这些都不会影响按钮被单击。
5、 现在这个最简单的控件已经完成,可以加载到主页面测试一下了。打开【BitCalculator】项目下的【MainPage.xaml】文件,首先添加对这个控件的引用:
xmlns:src="clr-namespace:BitLibrary;assembly=BitLibrary"
这里的“src”是一个前缀,也可以把它理解为引用名,你高兴的话可以换成其他的单词。之后所有需要使用到SpeedButton的地方都需要加上“src:”前缀。
(这一段是我介绍的那篇文章未描述步骤)还需要做一件事才能在MainPage.xaml中看到SpeedButton:在【BitCalculator】项目上单击鼠标右键,选中【添加引用】打开“添加引用”窗口,在【项目】栏中选中“BitLibrary”,单击【确定】按钮添加对BitLibrary的引用。
接下来,在MainPage.xaml中加入SpeedButton控件:
<src:SpeedButton/>
完成后,MainPage.xaml的所有代码应该象下面这个样子:
<UserControl x:Class="BitCalculator.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"
xmlns:src="clr-namespace:BitLibrary;assembly=BitLibrary"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<src:SpeedButton/>
</Grid>
</UserControl>
6、运行程序,我们发现浏览器中无任何内容,这很正常,我们的SpeedButton里面什么都没有。
第二步,修改控件模板:
我们首先看看使用常规方法是否能让SpeedButton显示一些内容:在【MainPage.xaml】中更改SpeedButton的声明如下:
<src:SpeedButton Width="30" Height="30" Background="Black"
Foreground="#FF000000" Content="HEX"
BorderBrush="Black" BorderThickness="2"/>
运行程序,我们发现除了Content里的“HEX“这几个字母外,其他的背景及边框根本没有按照我们的设想显示出来。这时,可以通过创建默认控件模板指定控件外观。
1、 在【BitLibrary】项目上单击鼠标右键,选择【添加】à【新建文件夹】添加一个新的文件夹,并把文件夹命名为“themes”。
2、 在【themes】文件夹上单击鼠标右键,选择【添加】à【新建项】,新建一个文本文件,并命名为:“generic.xaml”。这里需要注意,文件夹和文件的名称都不能搞错。
3、 打开generic.xaml文件,并填入如下代码:
<ResourceDictionary xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:BitLibrary;assembly=BitLibrary"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
<!-- SpeedButton Template -->
<Style TargetType="src:SpeedButton">
<Setter Property="Width" Value="30"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="#FF1F3B53"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="src:SpeedButton">
<Grid>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity" To="1"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="#F2FFFFFF"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="#CCFFFFFF"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="#7FFFFFFF"/>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="Background" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#FF6DBDD1"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity" To="1"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" To="#D8FFFFFF"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="#C6FFFFFF"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="#8CFFFFFF"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="#3FFFFFFF"/>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Border x:Name="Background" CornerRadius="3" Background="White" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
<Grid Background="{TemplateBinding Background}" Margin="1">
<Border Opacity="0" x:Name="BackgroundAnimation" Background="#FF448DCA" />
<Rectangle x:Name="BackgroundGradient" >
<Rectangle.Fill>
<LinearGradientBrush StartPoint=".7,0" EndPoint=".7,1">
<GradientStop Color="#FFFFFFFF" Offset="0" />
<GradientStop Color="#F9FFFFFF" Offset="0.375" />
<GradientStop Color="#E5FFFFFF" Offset="0.625" />
<GradientStop Color="#C6FFFFFF" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
<ContentPresenter
x:Name="contentPresenter"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
这段代码其实是从Button的模板直接拷贝过来的,这里只是稍作修改,把用不上的东西去掉,如Focus状态,Button模板可以在Silverlight的帮助文档中获取。我懒得去重新设计外观了,将就用一下吧。