一、引言
- WPF是一种用于创建富交互式桌面应用程序的框架,它为开发人员提供了丰富的界面元素和强大的数据绑定功能。通过使用WPF,开发人员可以创建出具有吸引力和高度自定义的用户界面。
1. 样式在WPF中的重要性
- 样式在WPF中扮演着至关重要的角色。通过使用样式,开发人员可以统一控制应用程序中所有元素的外观,简化对界面元素的修改和管理。样式可以应用于单个控件、控件类型或整个应用程序,从而实现全局的视觉一致性。
2. 样式的基本概念和作用
- 样式是WPF中用于定义控件外观的资源。它允许开发人员设置控件的属性,如背景颜色、字体、边框样式等。样式可以包含在一组属性设置中,并应用于具有特定目标类型的控件。通过使用样式,开发人员可以分离控件的外观和行为,使代码更加整洁和易于维护。
二、WPF样式基础
- WPF样式的基础知识,包括样式定义与作用、样式与资源的关系,以及样式的范围和作用域。
1.样式定义与作用
- 样式的基本概念:样式是一种定义控件外观的资源,它包含了一组属性设置,这些设置决定了控件的外观表现。样式通常包含在XAML文件中,并可以通过资源字典进行组织和管理。
- 样式在WPF中的主要作用:通过使用样式,开发人员可以统一控制应用程序中所有元素的外观,简化对界面元素的修改和管理。此外,样式还可以使代码更加整洁和易于维护,因为外观和行为的分离使得代码更具可读性和可维护性。
2.样式与资源
- 资源与样式之间的关系:WPF中的资源是用于共享可重用对象的一种机制。样式可以作为资源存在,这意味着它们可以在应用程序中的多个地方重用。通过将样式作为资源管理,可以避免重复的代码,并提高代码的效率和可维护性。
- 如何使用资源来管理样式:管理样式的资源可以通过资源字典进行组织。资源字典是一个容器,用于存储可重用的资源,如样式、画刷和模板等。在资源字典中定义的样式可以被应用程序中的任何控件所引用,从而实现全局的视觉一致性。
3.样式范围和作用域
- 样式的范围和作用域:样式的范围决定了它们可以被应用的控件类型和位置。通过设置样式的TargetType属性,可以指定样式应用于哪些类型的控件。同时,样式的范围也可以通过设置x:Key属性来限制,x:Key属性用于唯一标识样式,并确定其在资源字典中的位置。
- 如何控制样式的应用范围:除了通过TargetType和x:Key来控制样式的范围外,还可以使用Style.Triggers和DataTemplate.Triggers来根据条件触发样式的应用。通过设置触发器,可以根据控件的状态或数据值动态更改控件的外观。此外,还可以使用附加属性(附加属性)将样式应用到控件的其他方面,如附加事件处理程序或附加行为等。
三、WPF样式的创建与使用
- 介绍如何创建和使用WPF样式,包括简单样式的创建、使用触发器、样式继承与优先级、动态资源与绑定资源、在代码中应用样式,以及默认样式与控件模板。
1.简单样式的创建
- 在XAML中直接定义样式:通过在XAML文件中直接编写样式,可以轻松地为控件创建简单的外观定义。例如:
<Window.Resources>
<!--定义个所有Button样式-->
<!--指定 按钮背景颜色Background 属性值,字体大小FontSize属性值,字体颜色Foreground属性值-->
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="White"></Setter>
</Style>
</Window.Resources>
<Grid>
<Button Content="我是在XAML中直接定义样式" Width="300" Height="30"></Button>
</Grid>
上述代码定义了一个样式,该样式将所有Button控件的背景设置为蓝色,并将字体大小设置为18,并且设置字体颜色为白色。效果图如下:
- 在资源字典中创建和使用样式:资源字典是一个用于存储可重用资源的容器。通过将样式添加到资源字典中,可以在应用程序的任何位置引用和使用这些样式。例如:
<Window.Resources>
<!--定义个Button样式,并且定义资源键Key,然后可以通过资源的键引用样式并将其应用于指定的控件-->
<!--指定 按钮背景颜色Background 属性值,字体大小FontSize属性值,字体颜色Foreground属性值-->
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Red"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="White"></Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Row="0" Style="{StaticResource ButtonStyle}" Content="我是通过资源的键引用了样式" Width="300" Height="30"></Button>
<Button Grid.Row="1" Content="我没有使用资源键引用样式" Width="300" Height="30"></Button>
</Grid>
上述代码定义了一个样式并设置了资源键Key,通过样式Key来指定Button控件的背景设置为红色,并将字体大小设置为18,并且字体颜色为白色。效果图如下:
2.使用触发器(Triggers)
- 数据触发器(DataTriggers):数据触发器允许根据控件的属性或数据值来更改样式。例如:
<Window.Resources>
<Style TargetType="Button">
<Style.Triggers>
<!--切记要将绑定源设置本身RelativeSource={RelativeSource Self} 否则不会应用到控件上-->
<DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Self}}" Value="我触发了触发器效果">
<Setter Property="Background" Value="Green"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="myButton" Content="查看触发器效果" Width="300" Height="30" Click="myButton_Click"></Button>
</Grid>
using System.Windows;
using System.Windows.Controls;
namespace WpfStyleApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
// 做个判断切换看效果
var button = (Button)sender;
myButton.Content = button.Content.ToString() == "查看触发器效果" ? "我触发了触发器效果" : "查看触发器效果";
}
}
}
上述代码根据按钮内容Content 等于“我触发了触发器效果“时,触发触发器来改变按钮的背景颜色、字体大小,字体颜色,效果图如下:
- 属性触发器(Trigger):属性触发器则是基于控件的属性更改来应用样式。例如:
<Window.Resources>
<Style TargetType="Button">
<Style.Triggers>
<!--设置所有按钮触发触发器条件为IsFocused,表示获取焦点时触发-->
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button Content="点击或按Tab键让按钮获得焦点触发" Width="300" Height="30"></Button>
</Grid>
上述代码根据当按钮获得焦点时更改背景颜色,效果图如下:
3.样式继承与优先级
- 样式继承:通过设置样式的BasedOn属性,可以继承现有样式的设置。例如:
<Window.Resources>
<!--设置所有的Button继承ToolBar默认的按钮样式-->
<Style TargetType="Button" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"/>
</Window.Resources>
<Grid>
<Button Content="我继承了ToolBar的默认按钮样式" Width="300" Height="30"></Button>
</Grid>
上述代码继承ToolBar默认按钮样式的自定义样式,效果图如下:
- 优先级规则和冲突解决机制:样式的优先级是通过它们的顺序来决定的。内联样式(直接在元素上设置Style属性)拥有最高的优先级。样式选择器按照特定顺序决定优先级,从高到低:Keyed Style > Type-Based Style > BasedOn Style > Implicit Style。在同一级别(如同在ResourceDictionary内或同为内联样式)且优先级相同的情况下,最后定义的样式会覆盖先前定义的样式。这种优先级规则适用于同一级别的样式。如:
<Window.Resources>
<!-- 全局默认按钮样式 -->
<Style TargetType="Button">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<!-- 设置资源键Key,基于类型的选择器,具有较高优先级 -->
<Style x:Key="SpecialButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="Green"/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="默认样式按钮" Width="300" Height="30" />
<Button Grid.Row="1" Style="{StaticResource SpecialButtonStyle}" Content="Sytle覆盖了继承默认按钮样式" Width="300" Height="30" />
<!-- 在控件内部定义内联样式,该样式将覆盖所有外部定义的样式 -->
<Button Grid.Row="2" Content="内部样式覆盖了所有的外部样式" Style="{StaticResource SpecialButtonStyle}" Background="Yellow" Foreground="Red" Width="300" Height="30" >
</Button>
</Grid>
上述代码,全局样式、基于类型的选择器样式以及内联样式来设置按钮的背景颜色和前景颜色。优先级:内联样式>类型选择器样式>全局样式。效果图如下:
4.动态资源与代码中应用样式
- 动态资源:动态资源允许在运行时更改资源值。例如:
<Window.Resources>
<!--定义一个SolidColorBrush作为动态资源-->
<SolidColorBrush x:Key="ButtonBackground" Color="Green"/>
</Window.Resources>
<Grid>
<!-- 使用动态资源 -->
<Button Content="点击改变动态资源" Background="{DynamicResource ButtonBackground}" Foreground="White" Click="Button_Click" Width="300" Height="30"></Button>
</Grid>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfStyleApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// 获取窗口的资源字典
var resources = Application.Current.MainWindow.Resources;
// 更改动态资源 "ButtonBackground" 的颜色
resources["ButtonBackground"] = new SolidColorBrush(Colors.Red);
}
}
}
上述代码,点击按钮时,背景色将立即从绿色变为红色,效果图如下:
- 在C#代码中动态应用样式:可以通过编程方式在C#代码中动态设置控件的样式。使用FindResource和TryFindResource方法查找和应用资源:FindResource方法将搜索当前控件的资源字典以查找指定的资源,而TryFindResource方法将尝试查找指定的资源,如果找不到则返回null。这些方法在动态查找和设置资源时非常有用。
<Window.Resources>
<!--添加两个字典资源样式-->
<Style x:Key="FindResourceButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Red"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style x:Key="TryFindResourceButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Green"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="使用FindResource查找资源并应用样式" Width="350" Height="30" Click="Button_Click" />
<Button Grid.Row="1" Content="使用TryFindResource查找资源并应用样式" Width="350" Height="30" Click="Button_Click_1"/>
</Grid>
上述代码,通过FindResource和TryFindResource查找对应的资源,并应用到控件上,点击应用后效果图如下:
公众号“点滴分享技术猿”