下图显示的是已完成的按钮。
创建基本按钮
让我们首先从创建一个新项目并向窗口中添加几个按钮开始。
创建新的WPF 项目并向窗口中添加按钮
1.启动Visual Studio。
2.创建新的WPF 项目:在“文件”菜单上,指向“新建”,再单击“项目”。找到“Windows
应用程序(WPF)”模板并将项目命名为“AnimatedButton”。这将创建应用程序的主干。
3.添加基本的默认按钮:本演练中所需的全部文件均由该模板提供。通过在解决方案资源
管理器中双击Window1.xaml 文件来打开它。默认情况下,Window1.xaml 中存在一个Grid元素。移除Grid元素,并通过向Window1.xaml 中键入或复制和粘贴以下突
出显示的代码来向可扩展应用程序标记语言(XAML) 页面中添加几个按钮:
xmlns="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml/pre sentation" xmlns:x="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml" Title="AnimatedButton" Height="300" Width="300" Background="Black">
按F5 运行该应用程序;您应当能够看到类似下图的一组按钮。
现在您已经创建了基本按钮,这样就完成了在Window1.xaml 文件中的工作。本演练其余部分重点介绍如何在app.xaml 文件中为这些按钮定义样式和模板。
设置基本属性
接着,我们将会为这些按钮设置一些属性,以便控制按钮外观和布局。您将使用资源来为整个应用程序定义按钮属性,而不是为这些按钮单独设置属性。在概念上,应用程序资源与网页的外部级联样式表(CSS) 相似;但是,资源远比级联样式表(CSS) 强大,在本演练结束时您将明白这一点。若要进一步了解资源,请参见资源概述。
使用样式为按钮设置基本属性
1.定义Application.Resources 块:打开app.xaml 并添加下面突出显示的标记(如果尚
未添加):
xmlns="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml/pre sentation" xmlns:x="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml" StartupUri="Window1.xaml" >
资源范围由资源的定义位置来确定。如果资源是在app.xaml 文件
的 Application.Resoureses 中定义的,则将允许从应用程序中的任何位置使用资源。若要了解有关定义资源范围的更多信息,请参见资源概述。
2.创建一个样式并用该样式定义基本属性值:向 Application.Resources 块添加下面的标
记。此标记创建一个应用于该应用程序中所有按钮的Style,并将这些按钮的Width设置为90,将Margin设置为10:
TargetType属性指定将该样式应用于Button类型的所有对象。每个Setter都
为Style设置不同的属性值。因此,此时应用程序中的每个按钮的宽度都为90,边距都为10。如果您按F5 运行应用程序,则会看到下面的窗口。
您还可以对样式进行更多的处理,这包括以各种方式微调对象的目标、指定复杂的属性值,甚至将样式作为其他样式的输入。有关更多信息,请参见样式设置和模板化。
3.为资源设置样式属性值:使用资源,可以通过一种简单的方式来重用通常定义的对象和
值。为了使代码更加模块化,使用资源定义复杂值尤其有用。向app.xaml 添加下面突出显示的标记。
StartPoint="0,0" EndPoint="1,1">
Value="{StaticResource GrayBlueGradientBrush}" /> 您已经在 Application.Resources 块的正下方创建了一个名为“GrayBlueGradientBrush” 的资源。此资源将定义一个水平渐变。此资源可以在该应用程序中的任何位置(包括 在Background属性的按钮样式setter 内部中)用作属性值。现在,所有的按钮都具有此渐变的Background属性值。 按F5 运行该应用程序。其外观类似于下图: 创建一个定义按钮外观的模板 在本节中,将创建一个用来自定义按钮外观(表示)的模板。按钮表示是由几个赋予按钮独特外观的对象(包括矩形和其他组件)组成的。 到目前为止,对应用程序中按钮外观的控制已限制为更改按钮的属性。如果您希望更彻底地改变按钮的外观,该怎么办?使用模板可以强有力地控制对象的表示。由于模板可以在样式中使用,因此您可以将模板应用于所有应用了样式的对象(在本演练中为按钮)。 使用模板定义按钮的外观 1.设置模板:由于控件(如Button)具有Template属性,因此您可以像对Style中所设 置的其他属性值那样,使用Setter来定义模板属性值。向按钮样式中添加下面突出显示的标记。 StartPoint="0,0" EndPoint="1,1">
2.更改按钮表示:此时,您需要定义模板。添加下面突出显示的标记。此标记指定了两
个后跟DockPanel且具有圆角的Rectangle元素。DockPanel用于承载按钮
的ContentPresenter。 A ContentPresenter显示按钮的内容。本演练中,内容为文本("Button 1", "Button 2", "Button 3")。所有模板组件(矩形和DockPanel)都放置在一个Grid内。
Height="{TemplateBinding Height}" ClipToBounds="True "> HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}" RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" /> HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20" Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" /> Content="{TemplateBinding Content}" TextBlock.Foreground="Black" />
按F5 运行该应用程序。其外观类似于下图:
3.向模板中添加玻璃效果:接着将添加玻璃效果。首先创建一些用来生成玻璃渐变效果的
资源。将这些渐变资源添加到 Application.Resources 块中的任何位置:
StartPoint="0,0" EndPoint="1,1" Opacity="0.75" GradientStops="{StaticResource MyGlassGradientStopsRes ource}" /> 这些资源将用作按钮模板的Grid中所插入的矩形的Fill。向模板添加下面突出显示的标记。 ClipToBounds="True"> VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}" RadiusX="20" RadiusY="20" StrokeThickness="5" Fill=" Transparent" /> VerticalAlignment="Stretch" Stroke="Transparent" Str okeThickness="20" Fill="{TemplateBinding Background}" RadiusX="20" Rad iusY="20" /> VerticalAlignment="Stretch" StrokeThickness="2" RadiusX="10" RadiusY="10" Opacit y="0" Fill="{StaticResource MyGlassBrushResource}" RenderTransformOrigin="0.5,0.5">
Content="{TemplateBinding Content}" TextBlock.For eground="Black" /> 请注意,x:Name 属性为“glassCube”的矩形的Opacity为0,因此,当您运行该示例时,将看到上面并没有覆盖玻璃矩形。这是由于我们将在以后向该模板中添加用户与该按钮交互时将触发的触发器。但是,您可以通过将Opacity值更改为 1 并运行该应用程序来查看按钮现在的外观。请参见下图。在转至下一步之前,请将Opacity更改回0。 创建按钮交互性 在本节中,将创建属性触发器和事件触发器来更改属性值和运行动画,以响应用户操作(如将鼠标指针移到按钮上并单击)。 添加交互性(鼠标悬停、鼠标离开和单击等)的一个简便方法就是在模板或样式内部定义触发器。若要创建Trigger,需要定义一个属性“条件”,例如:按钮的IsMouseOver属性值等于 true。随后将定义在触发条件为true 时所发生的setter(操作)。 创建按钮交互性 1.添加模板触发器:向模板添加突出显示的标记。 Height="{TemplateBinding Height}" ClipToBounds="True "> VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}" RadiusX="20" RadiusY="20" StrokeThickness="5" Fill=" Transparent" /> VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20" Fill="{TemplateBinding Background}" RadiusX="20" R adiusY="20" /> VerticalAlignment="Stretch" StrokeThickness="2" RadiusX="10" RadiusY="10" Opac ity="0" Fill="{StaticResource MyGlassBrushResource}" RenderTransformOrigin="0.5,0.5"> Content="{TemplateBinding Content}" TextBlock.F oreground="Black" /> 2.添加属性触发器:向 ControlTemplate.Triggers 块添加突出显示的标记: Value="{DynamicResource {x:Static SystemColors.Highl ightBrushKey}}" /> TargetName="myContentPresenter"> 按F5 运行应用程序,并查看在将鼠标指针移到按钮上时的效果。 3.添加焦点触发器:接着,将添加一些类似的setter 来处理当按钮具有焦点时(例如, 当用户单击按钮之后)的情况。 Value="{DynamicResource {x:Static SystemColors.Highl ightBrushKey}}" /> TargetName="myContentPresenter"> Value="{DynamicResource {x:Static SystemColors.Highl ightBrushKey}}" /> 按F5 运行应用程序,并单击其中的某个按钮。请注意,在单击该按钮之后,该按钮仍具有焦点,因此它仍将保持突出显示状态。如果您单击另一个按钮,则新按钮将获得焦点,而上一个按钮则失去焦点。 4.为MouseEnter和MouseLeave添加动画:接下来我们将向触发器添加一些动 画。在 ControlTemplate.Triggers 块内部的任意位置添加下面的标记。 Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Chi ldren)[0].(ScaleTransform.ScaleX)" By="-0.1" Duration="0:0:0.5" /> Storyboard.TargetName="glassCube" Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Chi ldren)[0].(ScaleTransform.ScaleY)" By="-0.1" Duration="0:0:0.5" /> 当鼠标指针移到该按钮上时,玻璃矩形会收缩;当指针离开该按钮时,镜面矩形会返回到其正常大小。 当指针移到该按钮上(引发MouseEnter事件)时会触发两个动画。这些动画会使玻璃矩形沿着X 轴和Y 轴收缩。请注意DoubleAnimation元素的属性: Duration和By。Duration指定动画持续半秒多,By指定玻璃收缩10%。 第二个事件触发器(MouseLeave) 只是停止第一个触发器。当您停止某 个Storyboard时,所有的动画属性都恢复到其默认值。因此,当用户将指针移开按钮时,该按钮将返回到鼠标指针移到其上之前的状态。有关动画的更多信息,请参见动画概述。 5.添加单击按钮时的动画效果:最后一步是添加在用户单击按钮时将触发的触发 器。在 ControlTemplate.Triggers 块内部的任意位置添加下面的标记: Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Chi ldren)[1].(RotateTransform.Angle)" By="360" Duration="0:0:0.5" /> 按F5 运行应用程序,并单击其中的某个按钮。当您单击某个按钮时,玻璃矩形会旋转。 附详细代码如下: App.xaml xmlns="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml/presentation" xmlns:x="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml" StartupUri="MainWindow.xaml"> StartPoint="0,0" EndPoint="1,1" Opacity="0.75" GradientStops="{StaticResource MyGlassGradientStopsResource}" /> Height="{TemplateBinding Hei ght}" ClipToB ounds="True"> VerticalAlignment="Stretch" Stroke="{TemplateBindi ng Background}" RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" /> VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20" Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" /> VerticalAlignment="Stretch" StrokeThickness="2" Radi usX="10" RadiusY="10" Opacity="0" Fill="{StaticResource MyGlassBrushResource}" RenderTransformOrigin="0.5,0.5"> Content="{TemplateBinding Content}" TextBlock.Foreground="Black" /> TargetName="outerRectangle" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" /> TargetName="glassCube" /> TargetName="myContentPresenter"> TargetName="glassCube" /> Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" /> TargetName="glassCube" /> Storyboard.TargetName="glassC ube" Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" By="-0.1" Duration="0:0:0.5" /> Storyboard.TargetName="glassCube" Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" By="-0.1" Duration="0:0:0.5" /> BeginStoryboardName="mouseEnterBeginStoryboard" /> Storyboard.TargetName="glassC ube" Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)" By="360" Duration="0:0:0.5" /> MainWindow.xaml xmlns="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml/presentation" xmlns:x="https://www.doczj.com/doc/d113683656.html,/winfx/2006/xaml" Title="MainWindow" Height="300" Width="300" Background="Black">