WPF 样式与模板

参考

环境

软件/系统 版本 说明
Windows Windows 10 专业版 22H2 19045.4046
Microsoft Visual Studio Microsoft Visual Studio Community 2022 (64 位) - 17.6.5
Microsoft .Net SDK 8.0.101 手动安装
Microsoft .Net SDK 7.0.306 Microsoft Visual Studio 携带
.net 6.x 创建当前文章演示 WPF 项目时指定 .net 版本所选择的框架

正文

样式

  • 分类
    • 隐式应用样式
    • 显式应用样式
    • 扩展样式
    • 事件触发器
    • 属性触发器
    • 多属性触发器
    • 绑定触发器
    • 多绑定触发器
  • 演示
    image
  • XAML
    <Window
    	x:Class="学习.MainWindow"
    	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:local="clr-namespace:学习"
    	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    	xmlns:sys="clr-namespace:System;assembly=mscorlib"
    	Title="MainWindow"
    	Width="850"
    	Height="700"
    	mc:Ignorable="d">
    	<Window.Resources>
    		<!--  隐式应用样式,全局样式,应用到所有 TextBlock 上面  -->
    		<Style TargetType="TextBlock">
    			<Setter Property="FontSize" Value="15" />
    			<Setter Property="FontWeight" Value="ExtraBold" />
    		</Style>
    		<!--  显式应用样式,应用到  Style="{StaticResource 粗体} 上面  -->
    		<Style x:Key="粗体" TargetType="Button">
    			<Setter Property="FontSize" Value="15" />
    			<Setter Property="FontWeight" Value="ExtraBold" />
    		</Style>
    		<!--  扩展样式  -->
    		<Style
    			x:Key="扩展"
    			BasedOn="{StaticResource {x:Type Button}}"
    			TargetType="Button">
    			<Setter Property="FontSize" Value="30" />
    		</Style>
    		<!--  事件触发器,鼠标经过字体变大并半透明,离开变小。不需要为 MouseLeave 动画指定 To 值。 这是因为动画能够跟踪原始值。  -->
    		<Style x:Key="事件触发器" TargetType="Button">
    			<Setter Property="FontSize" Value="20" />
    			<Style.Triggers>
    				<EventTrigger RoutedEvent="Mouse.MouseEnter">
    					<EventTrigger.Actions>
    						<BeginStoryboard>
    							<Storyboard>
    								<DoubleAnimation
    									Storyboard.TargetProperty="FontSize"
    									To="90"
    									Duration="0:0:0.2" />
    							</Storyboard>
    						</BeginStoryboard>
    						<BeginStoryboard>
    							<Storyboard>
    								<DoubleAnimation
    									Storyboard.TargetProperty="Opacity"
    									To="0.5"
    									Duration="0:0:0.2" />
    							</Storyboard>
    						</BeginStoryboard>
    					</EventTrigger.Actions>
    				</EventTrigger>
    				<EventTrigger RoutedEvent="Mouse.MouseLeave">
    					<EventTrigger.Actions>
    						<BeginStoryboard>
    							<Storyboard>
    								<DoubleAnimation Storyboard.TargetProperty="FontSize" Duration="0:0:0.2" />
    							</Storyboard>
    						</BeginStoryboard>
    						<BeginStoryboard>
    							<Storyboard>
    								<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:0.2" />
    							</Storyboard>
    						</BeginStoryboard>
    					</EventTrigger.Actions>
    				</EventTrigger>
    			</Style.Triggers>
    		</Style>
    		<!--  属性触发器,选中的不透明并变大,未选中半透明并变小  -->
    		<Style x:Key="属性触发器" TargetType="CheckBox">
    			<Setter Property="Opacity" Value="0.5" />
    			<Style.Triggers>
    				<Trigger Property="IsChecked" Value="True">
    					<Trigger.Setters>
    						<Setter Property="Opacity" Value="1" />
    						<Setter Property="FontSize" Value="20" />
    					</Trigger.Setters>
    				</Trigger>
    			</Style.Triggers>
    		</Style>
    		<!--  多属性触发器,选中并且宽度为自动时,字体变大,变为不透明  -->
    		<Style x:Key="多属性触发器" TargetType="CheckBox">
    			<Setter Property="Opacity" Value="0.5" />
    			<Style.Triggers>
    				<MultiTrigger>
    					<MultiTrigger.Conditions>
    						<Condition Property="IsChecked" Value="True" />
    						<Condition Property="Width" Value="Auto" />
    					</MultiTrigger.Conditions>
    					<Setter Property="Opacity" Value="1" />
    					<Setter Property="FontSize" Value="30" />
    				</MultiTrigger>
    			</Style.Triggers>
    		</Style>
    		<!--  绑定触发器,当输入框 Texr = 50 的时候, TextBlock 背景变为红色  -->
    		<Style x:Key="绑定触发器" TargetType="TextBlock">
    			<Style.Triggers>
    				<DataTrigger Binding="{Binding Text, ElementName=绑定输入框}" Value="50">
    					<Setter Property="Background" Value="Red" />
    				</DataTrigger>
    			</Style.Triggers>
    		</Style>
    		<!--  多绑定触发器 ,当第一个输入框为66,第二个为77的时候,TextBlock背景变为红色  -->
    		<Style x:Key="多绑定触发器" TargetType="TextBlock">
    			<Style.Triggers>
    				<MultiDataTrigger>
    					<MultiDataTrigger.Conditions>
    						<Condition Binding="{Binding Text, ElementName=绑定输入框1}" Value="66" />
    						<Condition Binding="{Binding Text, ElementName=绑定输入框2}" Value="77" />
    					</MultiDataTrigger.Conditions>
    					<Setter Property="Background" Value="Red" />
    				</MultiDataTrigger>
    			</Style.Triggers>
    		</Style>
    	</Window.Resources>
    	<Grid>
    		<StackPanel>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>默认按钮</TextBlock>
    					<Button Content="Custom Button" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>粗体按钮</TextBlock>
    					<Button Content="Custom Button" Style="{StaticResource 粗体}" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>扩展样式按钮</TextBlock>
    					<Button Content="Custom Button" Style="{StaticResource 扩展}" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>事件触发器,鼠标经过字体变大并半透明,离开变小。</TextBlock>
    					<Button Content="Custom Button" Style="{StaticResource 事件触发器}" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>属性触发器,选中的不透明并变大,未选中半透明并变小</TextBlock>
    					<CheckBox Content="" Style="{StaticResource 属性触发器}" />
    					<CheckBox Content="" Style="{StaticResource 属性触发器}" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>多属性触发器,选中并且宽度为自动时,字体变大,变为不透明</TextBlock>
    					<CheckBox
    						Width="Auto"
    						Content=""
    						Style="{StaticResource 多属性触发器}" />
    					<CheckBox
    						Width="50"
    						Content=""
    						Style="{StaticResource 多属性触发器}" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock Style="{StaticResource 绑定触发器}">绑定触发器,当输入框 Texr = 50 的时候, TextBlock 背景变为红色</TextBlock>
    					<TextBox x:Name="绑定输入框" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock Style="{StaticResource 多绑定触发器}">多绑定触发器, 当第一个输入框为66,第二个为77的时候,TextBlock背景变为红色</TextBlock>
    					<TextBox x:Name="绑定输入框1" />
    					<TextBox x:Name="绑定输入框2" />
    				</StackPanel>
    			</Border>
    		</StackPanel>
    
    	</Grid>
    </Window>
    
    

模板

如果在 ContentControl 的 ControlTemplate 中声明了 ContentPresenter,ContentPresenter 将自动绑定到 ContentTemplate 和 Content 属性。 同样,ItemsControl 的 ControlTemplate 中的 ItemsPresenter 将自动绑定到 ItemTemplate 和 Items 属性。

  • 分类

    • ControlTemplate 控件模板
    • DataTemplate 数据模板
    • HierarchicalDataTemplate 表示具有层次结构数据的一种特殊类型的数据模板
    • DataTemplateSelector 动态选择数据模板
  • 演示
    image

  • XAML

    <Window
    	x:Class="学习.MainWindow"
    	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:local="clr-namespace:学习"
    	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    	xmlns:sys="clr-namespace:System;assembly=mscorlib"
    	Title="MainWindow"
    	Width="850"
    	Height="700"
    	mc:Ignorable="d">
    	<Window.Resources>
    		<Style x:Key="样式设置模板" TargetType="Button">
    			<!--  Set to true to not get any properties from the themes.  -->
    			<Setter Property="OverridesDefaultStyle" Value="True" />
    			<Setter Property="Template">
    				<Setter.Value>
    					<ControlTemplate TargetType="Button">
    						<Grid>
    							<Ellipse Fill="{TemplateBinding Background}" />
    							<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    						</Grid>
    					</ControlTemplate>
    				</Setter.Value>
    			</Setter>
    		</Style>
    		<ControlTemplate x:Key="控件模板" TargetType="Button">
    			<Grid>
    				<Ellipse Fill="{TemplateBinding Background}" />
    				<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    			</Grid>
    		</ControlTemplate>
    		<DataTemplate x:Key="数据模板" DataType="{x:Type local:Photo}">
    			<Image
    				Width="50"
    				Height="50"
    				Source="{Binding Source}" />
    		</DataTemplate>
    	</Window.Resources>
    	<Grid>
    		<StackPanel>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>通过Style设置控件模板</TextBlock>
    					<Button
    						Width="60"
    						Height="60"
    						Background="Red"
    						Content="按钮"
    						Style="{StaticResource 样式设置模板}" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>控件模板</TextBlock>
    					<Button
    						Width="60"
    						Height="60"
    						Background="Yellow"
    						Content="按钮"
    						Template="{StaticResource 控件模板}" />
    				</StackPanel>
    			</Border>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<TextBlock>数据模板</TextBlock>
    					<ListBox
    						Width="600"
    						Margin="10"
    						Background="Silver"
    						ItemTemplate="{StaticResource 数据模板}"
    						ItemsSource="{Binding list}"
    						SelectedIndex="0" />
    				</StackPanel>
    			</Border>
    		</StackPanel>
    
    	</Grid>
    </Window>
    
  • C#

    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace 学习
    {
    	/// <summary>
    	/// Interaction logic for MainWindow.xaml
    	/// </summary>
    	public partial class MainWindow : Window
    	{
    
    		public MainWindow()
    		{
    			InitializeComponent();
    			this.DataContext = new
    			{
    				list = new List<Photo>{
    					new Photo("/images/apple.jpg"),
    					new Photo("/images/apple.jpg"),
    					new Photo("/images/apple.jpg"),
    					new Photo("/images/apple.jpg"),
    				}
    			};
    		}
    	}
    	public class Photo
    	{
    		public Photo(string path)
    		{
    			Source = path;
    		}
    
    		public string Source { get; }
    
    		public override string ToString() => Source;
    	}
    }
    

视觉状态

控件始终处于特定的状态。 例如,当鼠标在控件的表面上移动时,该控件被视为处于公用状态 MouseOver。 没有特定状态的控件被视为处于公用 Normal 状态。 状态分为多个组,前面提到的状态属于 CommonStates 状态组。 大多数控件都有两个状态组:CommonStates 和 FocusStates。 在应用于控件的每个状态组中,控件始终处于每个组的一种状态,例如 CommonStates.MouseOver 和 FocusStates.Unfocused。 但是,控件不能处于同一组中的两种不同状态,例如 CommonStates.Normal 和 CommonStates.Disabled。

  • 演示
    image

  • XAML

    <Window
    	x:Class="学习.MainWindow"
    	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:local="clr-namespace:学习"
    	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    	xmlns:sys="clr-namespace:System;assembly=mscorlib"
    	Title="MainWindow"
    	Width="850"
    	Height="700"
    	mc:Ignorable="d">
    	<Window.Resources>
    		<ControlTemplate x:Key="B1" TargetType="Button">
    			<Grid>
    				<Grid.Background>
    					<SolidColorBrush x:Name="ButtonBrush" Color="Green" />
    				</Grid.Background>
    				<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    				<VisualStateManager.VisualStateGroups>
    					<VisualStateGroup x:Name="CommonStates">
    						<VisualStateGroup.Transitions>
    							<!--  Take one half second to trasition to the MouseOver state.  -->
    							<VisualTransition GeneratedDuration="0:0:0.5" To="MouseOver" />
    						</VisualStateGroup.Transitions>
    						<VisualState x:Name="Normal" />
    						<!--
    							Change the SolidColorBrush, ButtonBrush, to red when the
    							mouse is over the button.
    						-->
    						<VisualState x:Name="MouseOver">
    							<Storyboard>
    								<ColorAnimation
    									Storyboard.TargetName="ButtonBrush"
    									Storyboard.TargetProperty="Color"
    									To="Red" />
    							</Storyboard>
    						</VisualState>
    					</VisualStateGroup>
    				</VisualStateManager.VisualStateGroups>
    			</Grid>
    		</ControlTemplate>
    	</Window.Resources>
    	<Grid>
    		<StackPanel>
    			<Border
    				Margin="6"
    				Padding="6"
    				BorderBrush="Black"
    				BorderThickness="1">
    				<StackPanel>
    					<Button
    						Width="220"
    						Height="50"
    						Content="默认绿色,鼠标放上去变红"
    						Template="{StaticResource B1}" />
    				</StackPanel>
    			</Border>
    		</StackPanel>
    
    	</Grid>
    </Window>
    
    
posted @   夏秋初  阅读(139)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
历史上的今天:
2022-03-05 Java 死锁排查/JVM分析/OOM 异常快照分析(快照需要配置JVM在OOM时输出保存快照信息)
2022-03-05 Java 使用 Javap 命令反编译 class 文件为字节码的对应的文本形式(不是汇编)
点击右上角即可分享
微信分享提示