【WPF.NET开发】创建模板

本文内容

  1. 何时创建 ControlTemplate
  2. 先决条件
  3. 创建 ControlTemplate
  4. 使用模板
  5. 添加触发器
  6. 使用 VisualState

使用 Windows Presentation Foundation (WPF),可以使用自己的可重用模板自定义现有控件的可视结构和行为。 可以对应用程序、窗口和页面全局应用模板,也可以将模板直接应用于控件。 需要新建控件的大多数场景均可改为为现有控件创建新模板。

本文将介绍如何为 Button 控件创建新的 ControlTemplate。

1、何时创建 ControlTemplate

控件有许多属性,例如 Background、Foreground 和 FontFamily。 这些属性控制控件外观的不同方面,但可通过设置这些属性进行的更改有限。 例如,可以从 CheckBox 中将 Foreground 属性设置为蓝色,并将 FontStyle 设置为斜体。 要自定义设置控件中其他属性无法实现的控件外观时,则创建 ControlTemplate。

在多数用户界面中,按钮的总体外观相同:即一个包含某些文本的矩形。 若想要创建一个圆形的按钮,可以创建一个继承自该按钮或重新创建该按钮功能的新控件。 此外,新用户控件还会提供圆形视觉对象。

通过自定义现有控件的可视布局,可以避免创建新控件。 借助圆形按钮,可创建具有所需可视布局的 ControlTemplate。

另一方面,如果你需要具有新功能、其他属性和新设置的控件,可创建新的 UserControl。

2、先决条件

创建新的 WPF 应用程序,在 MainWindow.xaml(或选择的其他窗口)的 <Window> 元素中设置以下属性:

展开表

属性Value
TitleTemplate Intro Sample
SizeToContentWidthAndHeight
MinWidth250

将 <Window> 元素的内容设置为以下 XAML:

<StackPanel Margin="10"><Label>Unstyled Button</Label><Button>Button 1</Button><Label>Rounded Button</Label><Button>Button 2</Button>
</StackPanel>

最后,MainWindow.xaml 文件应如下所示:

<Window x:Class="IntroToStylingAndTemplating.Window1"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:local="clr-namespace:IntroToStylingAndTemplating"mc:Ignorable="d"Title="Template Intro Sample" SizeToContent="WidthAndHeight" MinWidth="250"><StackPanel Margin="10"><Label>Unstyled Button</Label><Button>Button 1</Button><Label>Rounded Button</Label><Button>Button 2</Button></StackPanel>
</Window>

如果你运行应用程序,它将如下所示:

unstyled-button.png?view=netdesktop-8.0

3、创建 ControlTemplate

声明 ControlTemplate 的最常见方法是在 XAML 文件的 Resources 部分中声明为资源。 模板是资源,因此它们遵从适用于所有资源的相同范围规则。 简言之,声明模板的位置会影响模板的应用范围。 例如,如果在应用程序定义 XAML 文件的根元素中声明模板,则该模板可以在应用程序中的任何位置使用。 如果在窗口中定义模板,则仅该窗口中的控件可以使用该模板。

首先,将 Window.Resources 元素添加到 MainWindow.xaml 文件:

<Window x:Class="IntroToStylingAndTemplating.Window2"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:local="clr-namespace:IntroToStylingAndTemplating"mc:Ignorable="d"Title="Template Intro Sample" SizeToContent="WidthAndHeight" MinWidth="250"><Window.Resources></Window.Resources><StackPanel Margin="10"><Label>Unstyled Button</Label><Button>Button 1</Button><Label>Rounded Button</Label><Button>Button 2</Button></StackPanel>
</Window>

使用以下属性集创建新的 <ControlTemplate>:

展开表

属性Value
x:Keyroundbutton
TargetTypeButton

此控制模板很简单:

  • 控件的根元素 Grid
  • 用于绘制按钮圆形外观的 Ellipse
  • 用于显示用户指定的按钮内容的 ContentPresenter
<ControlTemplate x:Key="roundbutton" TargetType="Button"><Grid><Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" /><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /></Grid>
</ControlTemplate>

TemplateBinding

创建新的 ControlTemplate 时,可能仍然想要使用公共属性更改控件外观。 TemplateBinding 标记扩展将 ControlTemplate 中元素的属性绑定到由控件定义的公共属性。 使用 TemplateBinding 时,可让控件属性用作模板参数。 换言之,设置控件属性后,该值将传递到包含 TemplateBinding 的元素。

椭圆形

请注意,<Ellipse> 元素的 Fill 和 Stroke 属性绑定到了控件的 Foreground 和 Background 属性。

ContentPresenter

此外,还将 <ContentPresenter> 元素添加到了模板。 此模板专为按钮设计,因此请注意该按钮继承自 ContentControl。 此按钮会显示该元素的内容。 可以在该按钮中设置任何内容,例如纯文本,甚至其他控件。 以下两个按钮均有效:

<Button>My Text</Button><!-- and --><Button><CheckBox>Checkbox in a button</CheckBox>
</Button>

在前面的两个示例中,将文本和复选框设置为 Button.Content 属性。 设置为内容的任何内容都可通过 <ContentPresenter> 显示,这是模板的功能。

若将 ControlTemplate 应用到 ContentControl 类型(例如 Button),将在元素树中搜索 ContentPresenter。 若找到了 ContentPresenter,模板会自动将控件的 Content 属性绑定到 ContentPresenter

4、使用模板

找到本文开头声明的按钮。

<StackPanel Margin="10"><Label>Unstyled Button</Label><Button>Button 1</Button><Label>Rounded Button</Label><Button>Button 2</Button>
</StackPanel>

将第二个按钮的 Template 属性设置为 roundbutton 资源:

<StackPanel Margin="10"><Label>Unstyled Button</Label><Button>Button 1</Button><Label>Rounded Button</Label><Button Template="{StaticResource roundbutton}">Button 2</Button>
</StackPanel>

若运行项目并查看结果,将看到此按钮具有圆形背景。

styled-button.png?view=netdesktop-8.0

你可能已注意到,此按钮不是一个圆形,而是倾斜的。 由于 <Ellipse> 元素的工作方式,它始终会扩展并填充可用空间。 将此按钮的 width 和 height 属性更改为同一个值,以使圆形均衡:

<StackPanel Margin="10"><Label>Unstyled Button</Label><Button>Button 1</Button><Label>Rounded Button</Label><Button Template="{StaticResource roundbutton}" Width="65" Height="65">Button 2</Button>
</StackPanel>

styled-uniform-button.png?view=netdesktop-8.0

5、添加触发器

即使已应用模板的按钮看上去与众不同,但它的行为与任何其他按钮相同。 若按下此按钮,将触发 Click 事件。 不过,你可能已注意到,当你将鼠标移到此按钮上方时,此按钮的视觉对象不会改变。 这些视觉对象交互均由模板定义。

通过 WPF 提供的动态事件和属性系统,你可以监视特定属性是否是某个值,必要时还可重新设置模板样式。 在此示例中,你将监视按钮的 IsMouseOver 属性。 当鼠标位于控件上方时,使用新颜色设置 <Ellipse> 的样式。 此触发器类型称为 PropertyTrigger。

必须为 <Ellipse> 添加一个可引用的名称,以便于触发器起作用。 将其命名为“backgroundElement”。

<Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />

接下来,将新的 Trigger 添加到 ControlTemplate.Triggers 集合。 此触发器将监视 IsMouseOver 事件是否为值 true

<ControlTemplate x:Key="roundbutton" TargetType="Button"><Grid><Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" /><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /></Grid><ControlTemplate.Triggers><Trigger Property="IsMouseOver" Value="true"></Trigger></ControlTemplate.Triggers>
</ControlTemplate>

接下来,将 <Setter> 添加到 <Trigger>,后者会将 <Ellipse> 的 Fill 属性更改为一种新颜色。

<Trigger Property="IsMouseOver" Value="true"><Setter Property="Fill" TargetName="backgroundElement" Value="AliceBlue"/>
</Trigger>

运行该项目。 请注意,当你将鼠标移到按钮上方时,<Ellipse> 的颜色会改变。

mouse-move-over-button.gif?view=netdesktop-8.0

6、使用 VisualState

视觉状态由控件定义和触发。 例如,当鼠标移到控件上方时,将触发 CommonStates.MouseOver 状态。 可以基于控件的当前状态对属性更改进行动画处理。 在上一部分中,当 IsMouseOver 属性为 true 时,使用 <PropertyTrigger> 将按钮的背景更改为 AliceBlue。 可改为创建一个视觉状态,来对此颜色的更改进行动画处理,以实现平稳过过渡。 

若要将 <PropertyTrigger> 转换为动画效果的可视状态,首先要从模板删除 <ControlTemplate.Triggers> 元素。

<ControlTemplate x:Key="roundbutton" TargetType="Button"><Grid><Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" /><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /></Grid>
</ControlTemplate>

接下来,在控件模板的 <Grid> 根中,添加 <VisualStateManager.VisualStateGroups>,其中包含 CommonStates 的 <VisualStateGroup>。 定义两种状态:Normal 和 MouseOver

<ControlTemplate x:Key="roundbutton" TargetType="Button"><Grid><VisualStateManager.VisualStateGroups><VisualStateGroup Name="CommonStates"><VisualState Name="Normal"></VisualState><VisualState Name="MouseOver"></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" /><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /></Grid>
</ControlTemplate>

触发 <VisualState> 时,将应用该状态中定义的任何动画。 为每种状态创建动画。 动画位于 <Storyboard> 元素中。 

此状态对椭圆填充进行动画处理,将其还原为控件的 Background 颜色。

  • 此状态对椭圆 Background 颜色进行动画处理,将其更改为新颜色 Yellow

    <Storyboard><ColorAnimation Storyboard.TargetName="backgroundElement" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" To="Yellow" Duration="0:0:0.3"/>
    </Storyboard>
    

现在,<ControlTemplate> 应如下所示。

<ControlTemplate x:Key="roundbutton" TargetType="Button"><Grid><VisualStateManager.VisualStateGroups><VisualStateGroup Name="CommonStates"><VisualState Name="Normal"><Storyboard><ColorAnimation Storyboard.TargetName="backgroundElement" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"To="{TemplateBinding Background}"Duration="0:0:0.3"/></Storyboard></VisualState><VisualState Name="MouseOver"><Storyboard><ColorAnimation Storyboard.TargetName="backgroundElement" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" To="Yellow" Duration="0:0:0.3"/></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Ellipse Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" /><ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" VerticalAlignment="Center" /></Grid>
</ControlTemplate>

运行该项目。 请注意,当你将鼠标移到按钮上方时,<Ellipse> 的颜色会进行动画处理。

mouse-move-over-button-visualstate.gif?view=netdesktop-8.0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/240417.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Android]CheckBox复选框

在Android开发中&#xff0c;复选框&#xff08;CheckBox&#xff09;是一种常用的控件&#xff0c;用于让用户在多个选项中进行选择。它通常用于表单中&#xff0c;让用户选择多个选项或者进行多项操作。在本篇博客中&#xff0c;我们将介绍如何在Android应用中使用CheckBox控…

《Python》面试常问:深拷贝、浅拷贝、赋值之间的关系(附可变与不可变)【用图文讲清楚!】

背景 想必大家面试或者平时学习经常遇到问python的深拷贝、浅拷贝和赋值之间的区别了吧&#xff1f;看网上的文章很多写的比较抽象&#xff0c;小白接收的难度有点大&#xff0c;于是乎也想自己整个文章出来供参考 可变与不可变 讲深拷贝和浅拷贝之前想讲讲什么是可变数据类型…

Win10 使用 Nmap 扫描 Andorid 设备开放端口

Nmap Nmap 是 网络探测工具和安全/端口扫描器。 官网链接 Nmap参考指南(Man Page) 官网下载地址 Downloading Nmap Nmap 下载安装 到官网下载对应操作系统的安装包&#xff0c; 默认配置&#xff0c;一直下一步安装即可。安装过程中备份下安装路径&#xff0c;后续用到。…

九州未来大模型一体机,加速AI应用落地

2023年已接近尾声&#xff0c;对于中国人工智能产业而言&#xff0c;这一年注定成为一个重要的转折点。在不同行业中&#xff0c;人工智能的应用不断涌现&#xff0c;众多大模型如雨后春笋般涌现。然而&#xff0c;在这一发展过程中也不可避免地出现了一系列问题&#xff0c;包…

vcruntime140_1.dll文件下载安装方法分享,如何安全修复vcruntime140_1.dll

遇到vcruntime140_1.dll文件遗失是用户在使用Windows操作系统时较为普遍遭遇到的一个问题&#xff0c;它归类于动态链接库&#xff08;DLL&#xff09;文件缺失的常见情形。在今天的内容里&#xff0c;我们将深入探讨如何正确地下载和安装vcruntime140_1.dll文件&#xff0c;以…

Google推出Gemini AI开发——10年工作经验的Android开发要被2年工作经验的淘汰了?

应用程序中利用 Gemini 前言&#xff08;可略过&#xff09;、使用 Gemini Pro 开发应用程序正文、Android Studio 中构建Gemini API Starter 应用第 1 步&#xff1a;在 AI 的新项目模板的基础上进行构建第 2 步&#xff1a;生成 API 密钥第 3 步&#xff1a;开始原型设计 正文…

Mybatis之增删改查

目录 一、引言 二、Mybatis——增 举例&#xff1a;添加用户 三、Mybatis——删 举例&#xff1a;删除用户 四、Mybatis——改 举例&#xff1a;修改用户 五、Mybatis——查 六、注意 END&#xff1a; 一、引言 书接上回&#xff0c;我们在了解完mybatis之后&#xff0c;肯…

STM32F4 HAL流水灯Proteus仿真

源码下载&#xff1a;https://download.csdn.net/download/zlkk00/88654405

CSS基础小练习

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>圣诞节快乐</title><style>/*设置背景色*/body{background-image:linear-gradient(green 50%,red 50%);background-size:100% 30px;}/*让div在页面居中*/#text{…

20231223使用Rockchip原厂的Android11调通Firefly的AIO-3399J开发板上的AP6356S

20231223使用Rockchip原厂的Android11调通Firefly的AIO-3399J开发板上的AP6356S 2023/12/23 14:14 开发板&#xff1a;Firefly的AIO-3399J【RK3399】 SDK&#xff1a;rk3399-android-11-r20211216.tar.xz【Android11】 Android11.0.tar.bz2.aa【ToyBrick】 Android11.0.tar.bz2…

C# Onnx yolov8n csgo player detection

目录 效果 模型信息 项目 代码 下载 C# Onnx yolov8n csgo player detection 效果 模型信息 Model Properties ------------------------- date&#xff1a;2023-12-22T15:01:08.014205 author&#xff1a;Ultralytics task&#xff1a;detect license&#xff1a;AGPL-…

学会这套Pytest接口自动化测试框架,击败99%的人

Pytest 的下载安装 1、Python3 使用 pip install -U pytest 安装 2、查看 pytest 版本信息 pytest --version 3、pytest 用例的执行规则&#xff1a; ①测试文件以 test_xx.py 命名需要以 test_开头&#xff08;或_test 结尾&#xff09; ②测试类以 Test_开头&#xff0…

智能优化算法应用:基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.骑手优化算法4.实验参数设定5.算法结果6.…

跨平台应用程序开发软件,携RAD Studio 12新版上线

RAD Studio 是一款专为程序员而准备的跨平台应用程序开发软件&#xff0c;内置Delphi和CBuilder这两种开发工具&#xff0c;另外还提供了新的C功能&#xff0c;扩展了对ExtJS的RAD服务器支持&#xff0c;增强了对vcL的高dpi支持&#xff0c;提高了firemonk (FMX)的质量等等&…

C++结合OpenCV:掌握图像基础与处理

本文详细介绍了使用 OpenCV4 进行图像处理的基础知识和操作。内容包括图像的基础概念、色彩空间理解、以及如何在 C 中进行图像读取、显示和基础操作。 1.图像的基本概念与术语 图像表示 在计算机视觉中&#xff0c;图像通常表示为一个二维或三维的数组。二维数组表示灰度图像&…

[SQL]实验 视图和索引的应用

实验目的&#xff1a; [实验目的和要求] 1、掌握视图的创建、修改和重命名的方法 2、掌握视图中数据的操作 3、了解索引的作用 4、掌握索引的创建方法 实验步骤&#xff1a; 1、在销售管理数据库中&#xff0c;创建一个女职工视图&#xff0c;包括员工的编号、姓名、性别、雇佣…

网站怎么才能做好SEO?网站SEO指引!!

在当今互联网的激烈竞争中&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;已成为提升网站流量和吸引更多用户的关键手段。为了帮助您更好地掌握SEO网站优化技巧&#xff0c;本文将深入探讨以下几个方面&#xff1a; 一、关键词策略 关键词策略是SEO优化的基石。正确选择…

【WPF.NET开发】创建样式

本文内容 创建样式隐式应用样式显式应用样式以编程方式应用样式扩展样式TargetType 属性与 x:Key 属性之间的关系 使用 Windows Presentation Foundation (WPF)&#xff0c;可以使用自己的可重用样式自定义现有控件的外观。 可以对应用、窗口和页面全局应用样式&#xff0c;也…

Ansible的脚本---Playbook剧本编写

playbook的组成部分 1、 tasks&#xff1a;任务 在目标主机上需要执行的操作。使用模块定义这些操作。每个任务都是一个模块的调用。 2、 variables&#xff1a;变量 用于存储和传递数据。类似于shell脚本中的变量。变量可以自定义。可以在playbook当中定义为全局变量&…

基于Vite+Vue3 给项目引入Axios

基于ViteVue3 给项目引入Axios,方便与后端进行通信。 系列文章指路&#x1f449; 系列文章-基于Vue3创建前端项目并引入、配置常用的库和工具类 文章目录 安装依赖新建src/config/config.js 用于存放常用配置进行简单封装解决跨域问题调用尝试 安装依赖 npm install axios …