当前位置: 首页 > news >正文

WPF学习(三)

文章目录

  • 一 、Template
    • 1.1 重点掌握
    • 1.2 my example
  • 二、 Resource
    • 2.1 重点掌握
    • 2.2 三种引用方式
  • 三、关键帧

一 、Template

1.1 重点掌握

在WPF(Windows Presentation Foundation)中,ControlTemplate 是定义控件外观和行为的核心机制。一个模板可以包含以下类型的元素和功能:

一、可视化元素
模板的核心是定义控件的视觉结构,可包含:

  1. 布局容器

    • GridStackPanelCanvasDockPanel 等,用于组织子元素的排列方式。
    • 示例:
      <ControlTemplate TargetType="Button"><Grid><!-- 按钮内容将在此处显示 --></Grid>
      </ControlTemplate>
      
  2. 图形元素

    • RectangleEllipsePathLine 等形状,用于创建自定义外观。
    • 示例:
      <Rectangle x:Name="Background" Fill="Blue" />
      
  3. 内容展示

    • ContentPresenter:显示控件的 Content 属性(如按钮的文本)。
    • ItemsPresenter:用于 ItemsControl(如 ListBox)显示子项集合。
    • 示例:
      <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
      
  4. 装饰器

    • BorderDropShadowEffectBlurEffect 等,用于添加边框、阴影或视觉效果。
    • 示例:
      <Border BorderBrush="Black" BorderThickness="1" CornerRadius="4"><!-- 内部元素 -->
      </Border>
      

二、触发器(Triggers)
用于根据控件状态改变外观,包括:

  1. 属性触发器(PropertyTrigger)

    • 基于控件属性值触发(如 IsMouseOverIsPressed)。
    • 示例:
      <Trigger Property="IsMouseOver" Value="True"><Setter TargetName="Background" Property="Fill" Value="LightBlue" />
      </Trigger>
      
  2. 事件触发器(EventTrigger)

    • 基于事件触发动画(如 MouseEnterLoaded)。
    • 示例:
      <EventTrigger RoutedEvent="Button.Click"><BeginStoryboard><Storyboard><!-- 动画定义 --></Storyboard></BeginStoryboard>
      </EventTrigger>
      
  3. 数据触发器(DataTrigger)

    • 基于绑定数据触发(需配合 DataContext 使用)。

三、动画(Animations)
通过 Storyboard 定义平滑过渡效果,可应用于:

  • 属性动画:如改变颜色、大小、位置等。
    示例:

    <DoubleAnimation Storyboard.TargetName="Background" Storyboard.TargetProperty="Width" From="0" To="100" Duration="0:0:0.5" />
    
  • 关键帧动画:定义多个中间状态,实现更复杂的动画路径。

四、命名元素引用(x:Name)
为元素分配名称,以便在模板内部或触发器中引用:

<Rectangle x:Name="Highlight" Fill="Red" Visibility="Hidden" />

在触发器中使用:

<Trigger Property="IsSelected" Value="True"><Setter TargetName="Highlight" Property="Visibility" Value="Visible" />
</Trigger>

五、模板绑定(TemplateBinding)
将模板内元素的属性绑定到控件的属性:

<Border BorderThickness="{TemplateBinding BorderThickness}" />

常见绑定属性:WidthHeightForegroundBackground 等。

六、样式与资源

  1. 内联样式:在模板内定义局部样式。

    <Style TargetType="TextBlock"><Setter Property="FontSize" Value="14" />
    </Style>
    
  2. 资源引用:使用 StaticResourceDynamicResource 引用外部资源(如颜色、画笔)。

    <SolidColorBrush x:Key="ButtonHoverBrush" Color="LightBlue" />
    <!-- 在模板中使用 -->
    <Setter Property="Background" Value="{StaticResource ButtonHoverBrush}" />
    

七、逻辑交互元素

  1. 子控件:在模板中嵌入其他控件(如 TextBoxCheckBox)。

    <CheckBox x:Name="ToggleButton" Content="选项" />
    
  2. 交互行为:通过 Behavior(需引用 System.Windows.Interactivity)添加自定义交互逻辑。

八、模板参数(TemplatePart)
使用 TemplatePart 特性声明模板需要的特定元素,供控件逻辑使用:

[TemplatePart(Name = "PART_ContentHost", Type = typeof(FrameworkElement))]
public class CustomControl : Control
{// 控件逻辑
}

完整示例:自定义按钮模板

<ControlTemplate TargetType="Button"><Grid><!-- 背景 --><Rectangle x:Name="Background" Fill="{TemplateBinding Background}" RadiusX="4" RadiusY="4" /><!-- 内容显示 --><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /><!-- 鼠标悬停时的高亮效果 --><Rectangle x:Name="Highlight" Fill="LightBlue" RadiusX="4" RadiusY="4" Opacity="0" /></Grid><ControlTemplate.Triggers><!-- 鼠标悬停时显示高亮 --><Trigger Property="IsMouseOver" Value="True"><Setter TargetName="Highlight" Property="Opacity" Value="0.5" /></Trigger><!-- 点击时改变背景色 --><Trigger Property="IsPressed" Value="True"><Setter TargetName="Background" Property="Fill" Value="DarkBlue" /></Trigger></ControlTemplate.Triggers>
</ControlTemplate>

总结
ControlTemplate 可以包含几乎所有WPF元素,核心功能是:

  • 定义控件的视觉结构(布局、形状、内容)
  • 通过触发器实现状态驱动的外观变化
  • 使用动画增强交互体验
  • 通过模板绑定保持与控件属性的同步

合理使用模板,可以完全自定义任何控件的外观和行为,同时保留其原始功能。

1.2 my example

在这里插入图片描述

<Window x:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="450" Width="800"><Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><Ellipse x:Name="myEllipse"><Ellipse.Fill><SolidColorBrush x:Name="ellipseBrush" Color="Red" /></Ellipse.Fill></Ellipse><Rectangle Grid.Column="1" x:Name="rectangle" Width="10"><Rectangle.Fill><SolidColorBrush Color="Red" /></Rectangle.Fill></Rectangle><Button x:Name="myButton" Grid.Row="1" Width="250" Height="50" Content="动画触发启动"><Button.Template><ControlTemplate TargetType="Button"><Border BorderBrush="Fuchsia" BorderThickness="2"><Grid><!-- 定义动画目标Rectangle --><Rectangle x:Name="rectangle" Fill="LightBlue" Width="10" Height="{TemplateBinding Height}" HorizontalAlignment="Left"/><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/></Grid></Border><ControlTemplate.Triggers><!-- 鼠标悬停时启动动画 --><Trigger Property="IsMouseOver" Value="true"><Trigger.EnterActions><BeginStoryboard><Storyboard><DoubleAnimation Storyboard.TargetName="rectangle" Storyboard.TargetProperty="Width"Duration="0:0:1"From="10" To="250"AutoReverse="True"RepeatBehavior="Forever"/></Storyboard></BeginStoryboard></Trigger.EnterActions><!-- 鼠标离开时停止动画 --><Trigger.ExitActions><BeginStoryboard><Storyboard><DoubleAnimation Storyboard.TargetName="rectangle"Storyboard.TargetProperty="Width"Duration="0:0:0.3"To="10"/></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Button.Template></Button><Grid.Triggers><EventTrigger RoutedEvent="FrameworkElement.Loaded"><BeginStoryboard><Storyboard><!-- 第一个椭圆的动画 --><ColorAnimation Storyboard.TargetName="ellipseBrush"Storyboard.TargetProperty="Color"Duration="00:00:10"From="Red" To="Black"AutoReverse="True"RepeatBehavior="Forever"SpeedRatio="10"/><DoubleAnimation Storyboard.TargetName="rectangle"Storyboard.TargetProperty="Width"Duration="00:00:10"From="10" To="200"AutoReverse="True"RepeatBehavior="Forever"SpeedRatio="5"/></Storyboard></BeginStoryboard></EventTrigger></Grid.Triggers></Grid>
</Window>

二、 Resource

在WPF中,Resources 是一种强大的机制,用于集中管理和复用应用程序中的各种资源(如样式、画笔、动画等)。以下是关于 Resources 的详细使用指南:

2.1 重点掌握

一、资源的定义与分类
资源可以定义在多个位置,按作用域分为:

  1. 应用程序级别:在 App.xaml 中定义,全局可用

    <Application.Resources><SolidColorBrush x:Key="PrimaryColor" Color="#3498DB" />
    </Application.Resources>
    
  2. 窗口/控件级别:在窗口或控件的 Resources 中定义,仅在当前范围内可用

    <Window.Resources><Style x:Key="ButtonStyle" TargetType="Button"><Setter Property="Background" Value="{StaticResource PrimaryColor}" /></Style>
    </Window.Resources>
    
  3. 局部资源:在元素内部定义,仅作用于该元素及其子元素

    <Grid.Resources><DataTemplate x:Key="PersonTemplate"><TextBlock Text="{Binding Name}" /></DataTemplate>
    </Grid.Resources>
    

二、常见资源类型

  1. 样式(Style)
    统一设置控件的外观属性:

    <Style x:Key="TextBoxStyle" TargetType="TextBox"><Setter Property="Foreground" Value="DarkBlue" /><Setter Property="BorderBrush" Value="Gray" />
    </Style>
    
  2. 画笔(Brush)
    定义颜色、渐变等填充效果:

    <SolidColorBrush x:Key="AccentBrush" Color="Orange" />
    <LinearGradientBrush x:Key="GradientBrush" StartPoint="0,0" EndPoint="1,1"><GradientStop Color="White" Offset="0" /><GradientStop Color="LightGray" Offset="1" />
    </LinearGradientBrush>
    
  3. 模板(Template)
    自定义控件的视觉结构:

    <ControlTemplate x:Key="CustomButtonTemplate" TargetType="Button"><Border Background="{TemplateBinding Background}" CornerRadius="5"><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /></Border>
    </ControlTemplate>
    
  4. 数据模板(DataTemplate)
    定义数据的显示方式:

    <DataTemplate x:Key="EmployeeTemplate"><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Name}" Margin="5" /><TextBlock Text="{Binding Age}" Margin="5" /></StackPanel>
    </DataTemplate>
    
  5. 动画(Storyboard)
    预定义动画效果:

    <Storyboard x:Key="FadeInAnimation"><DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.5" />
    </Storyboard>
    

三、资源的引用方式
使用 StaticResourceDynamicResource 标记扩展引用资源:

  1. 静态资源(StaticResource)
    在编译时解析,性能较高,适合不会动态变化的资源:

    <Button Style="{StaticResource ButtonStyle}" />
    <Rectangle Fill="{StaticResource GradientBrush}" />
    
  2. 动态资源(DynamicResource)
    在运行时动态解析,支持资源值的实时更新:

    <TextBlock Foreground="{DynamicResource AccentColor}" />
    

四、资源字典(ResourceDictionary)
将资源单独提取到 .xaml 文件中,实现跨项目共享:

  1. 创建资源字典文件(如 Styles.xaml):

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Style x:Key="TitleText" TargetType="TextBlock"><Setter Property="FontSize" Value="24" /><Setter Property="FontWeight" Value="Bold" /></Style>
    </ResourceDictionary>
    
  2. 在应用程序中引用

    <Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Styles.xaml" /><ResourceDictionary Source="Themes/BlueTheme.xaml" /></ResourceDictionary.MergedDictionaries></ResourceDictionary>
    </Application.Resources>
    

五、隐式资源(无Key的资源)
通过省略 x:Key 并指定 TargetType,创建可自动应用的资源:

<Style TargetType="Button"><Setter Property="Background" Value="LightGray" /><Setter Property="Foreground" Value="Black" />
</Style>

所有未显式设置样式的 Button 都会自动应用此样式。

六、资源查找顺序
当使用 StaticResourceDynamicResource 引用资源时,WPF会按以下顺序查找:

  1. 当前元素的 Resources 集合
  2. 父元素的 Resources 集合(向上递归查找)
  3. 窗口/页面的 Resources 集合
  4. 应用程序级别的 Resources 集合(App.xaml
  5. 所有合并的资源字典
  6. 系统资源(如默认字体、颜色等)

七、示例:完整应用
App.xaml(定义全局资源):

<Application.Resources><SolidColorBrush x:Key="PrimaryColor" Color="#2C3E50" /><SolidColorBrush x:Key="AccentColor" Color="#E74C3C" /><Style x:Key="MainWindowStyle" TargetType="Window"><Setter Property="Background" Value="{StaticResource PrimaryColor}" /></Style>
</Application.Resources>

MainWindow.xaml(使用资源):

<Window x:Class="MyApp.MainWindow"Style="{StaticResource MainWindowStyle}"><Window.Resources><Style x:Key="TitleText" TargetType="TextBlock"><Setter Property="FontSize" Value="24" /><Setter Property="Foreground" Value="{StaticResource AccentColor}" /></Style></Window.Resources><Grid><TextBlock Style="{StaticResource TitleText}" Text="欢迎使用我的应用" /><Button Content="点击" Background="{StaticResource AccentColor}" /></Grid>
</Window>

八、注意事项

  1. 资源键必须唯一:同一范围内不能有重复的 x:Key
  2. 静态资源 vs 动态资源
    • 静态资源在初始化时解析,修改资源不会影响已应用的元素
    • 动态资源会实时更新,但性能开销略高
  3. 避免循环引用:资源间的引用不能形成闭环
  4. 资源优先级:局部资源会覆盖全局资源

合理使用 Resources 可以大幅提高代码的可维护性和复用性,使UI设计更加统一和灵活。

2.2 三种引用方式

要使用在 Resources 中定义的 mybutton 样式,你需要通过 Style 属性将其应用到 Button 控件上。以下是具体的实现方法:

方法1:显式引用命名样式
如果在资源中定义了带 x:Key 的样式(如 mybutton),需要通过 Style="{StaticResource mybutton}" 显式应用:

<Window.Resources><!-- 定义名为"mybutton"的样式 --><Style x:Key="mybutton" TargetType="Button"><Setter Property="Background" Value="LightBlue" /><Setter Property="Foreground" Value="DarkBlue" /><Setter Property="FontSize" Value="16" /></Style>
</Window.Resources><Grid><!-- 应用自定义样式 --><Button Style="{StaticResource mybutton}" Content="自定义按钮" />
</Grid>

方法2:隐式应用样式(无 x:Key
如果希望所有 Button 自动应用该样式,可以省略 x:Key 只保留 TargetType

<Window.Resources><!-- 所有Button将自动应用此样式 --><Style TargetType="Button"><Setter Property="Background" Value="LightBlue" /><Setter Property="Foreground" Value="DarkBlue" /><Setter Property="FontSize" Value="16" /></Style>
</Window.Resources><Grid><!-- 无需指定Style属性,自动应用上面的样式 --><Button Content="自动应用样式的按钮" />
</Grid>

方法3:基于现有样式扩展
如果想在默认 Button 样式基础上扩展,可以使用 BasedOn 属性:

<Window.Resources><Style x:Key="mybutton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}"><Setter Property="Background" Value="LightBlue" /><Setter Property="Foreground" Value="DarkBlue" /></Style>
</Window.Resources><Grid><Button Style="{StaticResource mybutton}" Content="扩展默认样式的按钮" />
</Grid>

关键点说明

  1. x:Key 的作用

    • x:Key(如 x:Key="mybutton"):需显式引用
    • x:Key:隐式应用到所有 TargetType 类型的控件
  2. 资源作用域

    • <Window.Resources> 中定义:仅当前窗口可用
    • <Application.Resources> 中定义:全局所有窗口可用
  3. 引用语法

    • StaticResource:编译时解析(推荐)
    • DynamicResource:运行时动态解析(适用于需要实时更新的场景)

完整示例
以下是一个完整的窗口示例,包含自定义 Button 样式的定义和使用:

<Window x:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="自定义按钮样式" Height="300" Width="400"><Window.Resources><!-- 自定义按钮样式 --><Style x:Key="mybutton" TargetType="Button"><Setter Property="Background" Value="#3498DB" /><Setter Property="Foreground" Value="White" /><Setter Property="FontSize" Value="14" /><Setter Property="Padding" Value="8,4" /><Setter Property="BorderThickness" Value="0" /><Setter Property="CornerRadius" Value="4" /><!-- 鼠标悬停效果 --><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="#2980B9" /></Trigger></Style.Triggers></Style></Window.Resources><Grid><!-- 使用自定义样式的按钮 --><Button Style="{StaticResource mybutton}" Content="点击我" HorizontalAlignment="Center" VerticalAlignment="Center" /><!-- 普通按钮(未应用样式) --><Button Content="普通按钮" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,20" /></Grid>
</Window>

常见问题

  1. 样式不生效

    • 检查 x:Key 拼写是否正确
    • 确保 TargetType 与控件类型匹配(如 TargetType="Button"
  2. 全局应用样式
    将样式定义移至 App.xaml<Application.Resources> 中:

    <Application.Resources><Style x:Key="mybutton" TargetType="Button"><!-- 样式内容 --></Style>
    </Application.Resources>
    

通过上述方法,你可以灵活地复用自定义的 Button 样式,提高代码的可维护性和一致性。

三、关键帧

在WPF中,含有关键帧的时间线(KeyFrame Animation)不含关键帧的时间线(基本动画) 主要区别在于动画的复杂度和控制精度。以下是具体对比:

特性基本动画关键帧动画
变化路径线性(直线)支持非线性(曲线、突变)
控制点数量2个(起始值和结束值)≥2个(可定义任意数量关键帧)
时间控制整体持续时间(Duration)每个关键帧可单独指定时间
插值方式固定线性插值支持线性、曲线、离散等多种方式
复杂度简单高(适合复杂动画)
XAML代码量多(需要定义多个关键帧)

一、基本动画(不含关键帧)
特点

  1. 简单线性变化
    从起始值(From)到结束值(To)或相对变化值(By)进行线性插值。
    示例

    <DoubleAnimation From="0" To="100" Duration="0:0:1" Storyboard.TargetProperty="Width" />
    
  2. 单一变化路径
    只支持直线过渡,无法定义复杂的变化曲线。

  3. 适用场景

    • 简单的淡入淡出、大小缩放、位置移动等线性变化。

二、关键帧动画(含有关键帧)
特点

  1. 多阶段复杂变化
    通过定义多个关键帧(KeyFrame) 指定不同时间点的属性值,支持非线性变化。
    示例

    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Width" Duration="0:0:2"><LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />    <!-- 0秒时宽度为0 --><LinearDoubleKeyFrame Value="100" KeyTime="0:0:1" />  <!-- 1秒时宽度为100 --><SplineDoubleKeyFrame Value="150" KeyTime="0:0:1.5"  <!-- 1.5秒时宽度为150(使用曲线插值) -->KeySpline="0.5,0 0.7,1" />  <!-- 定义贝塞尔曲线,控制加速/减速 --><DiscreteDoubleKeyFrame Value="200" KeyTime="0:0:2" /> <!-- 2秒时立即跳转到200 -->
    </DoubleAnimationUsingKeyFrames>
    
  2. 多种插值方式

    • LinearKeyFrame:线性插值(匀速变化)
    • SplineKeyFrame:使用贝塞尔曲线插值(可自定义加速/减速)
    • DiscreteKeyFrame:离散变化(瞬间跳转)
  3. 精确时间控制
    每个关键帧都可以指定精确的 KeyTime,实现复杂的时间序列。

  4. 适用场景

    • 不规则运动(如弹跳、弹性效果)
    • 多阶段动画(如先加速后减速)
    • 复杂过渡效果(如模拟物理运动)

三、核心区别对比表

特性基本动画关键帧动画
变化路径线性(直线)支持非线性(曲线、突变)
控制点数量2个(起始值和结束值)≥2个(可定义任意数量关键帧)
时间控制整体持续时间(Duration)每个关键帧可单独指定时间
插值方式固定线性插值支持线性、曲线、离散等多种方式
复杂度简单高(适合复杂动画)
XAML代码量多(需要定义多个关键帧)

四、何时选择哪种方式?

  • 选择基本动画
    当动画是简单的线性变化,且不需要精细控制中间过程时(如淡入淡出、匀速移动)。

  • 选择关键帧动画

    • 需要非线性变化(如物体弹跳、弹性效果)。
    • 需要在特定时间点触发特定值(如动画的暂停、跳跃)。
    • 需要组合多种变化方式(如先加速后减速)。

五、示例对比
1. 基本动画:匀速淡入

<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1" />

2. 关键帧动画:弹性淡入(先过度再回弹)

<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="0:0:1.5"><LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" /><SplineDoubleKeyFrame Value="1.2" KeyTime="0:0:0.8" KeySpline="0.5,0 0.7,1" />  <!-- 先超过目标值(1.2) --><SplineDoubleKeyFrame Value="1" KeyTime="0:0:1.5" KeySpline="0.3,0 0.5,1" />  <!-- 回弹到最终值(1) -->
</DoubleAnimationUsingKeyFrames>

总结
关键帧动画是基本动画的超集,提供了更强大的控制能力,但也增加了代码复杂度。根据动画需求的简单或复杂程度,选择合适的方式可以在保证效果的同时优化代码结构。

http://www.lqws.cn/news/593083.html

相关文章:

  • 08跨域
  • vue-i18n+vscode+vue 多语言使用
  • Mac 部署Latex OCR并优化体验(打包成App并支持全局快捷键)
  • WebSocket技术全面解析:从历史到实践
  • (Python)Python基础语法介绍(二)(Python基础教学)
  • 老年护理实训室建设方案:打造沉浸式护理实训环境
  • pulseaudio实现音频的网络传输
  • Wireshark TS | 诡异的光猫网络问题
  • 中心效应:多中心临床试验的关键考量
  • Selector组件组件
  • sentinel滑动窗口及熔断限流实现原理
  • STM32作为主机识别鼠标键盘
  • Gradio全解13——MCP协议详解(5)——Python包命令:uv与uvx实战
  • Easy Window UI设计器 - 图表组件 10秒完成UI效果
  • Xposed框架深度解析:Android系统级Hook实战指南
  • Flask+LayUI开发手记(十):构建统一的选项集合服务
  • QGIS合并、拆分SHP文件
  • 深入理解栈的合法弹出序列验证算法
  • docusaurus初步体验
  • Bootstrap 安装使用教程
  • 多bin技术:为LoRa项目赋能的高效远程升级方案
  • OpenCV CUDA模块设备层-----双曲正切函数tanh()
  • Terraform Helm:微服务基础设施即代码
  • 《UE5_C++多人TPS完整教程》学习笔记39 ——《P40 远程过程调用(Remote Procedure Calls)》
  • LabVIEW自动扶梯振动监测
  • RabbitMQ简单消息发送
  • Node.js与Express框架的深度整合
  • beego打包发布到Centos系统及国产麒麟系统完整教程
  • react-数据Mock实现——json-server
  • 飞算 JavaAI 开发助手:深度学习驱动下的 Java 全链路智能开发新范式