Button加入等待动画,先运行软件看下效果

建立BusyFrameAnimation类,在类中创建Button中依赖属性IsBusyProperty

public class BusyFrameAnimation : DependencyObject{public static bool GetIsBusy(DependencyObject property){return (bool)property.GetValue(IsBusyProperty);}public static void SetIsBusy(DependencyObject property, bool value){property.SetValue(IsBusyProperty, value);}public static readonly DependencyProperty IsBusyProperty =DependencyProperty.RegisterAttached("IsBusy", typeof(bool), typeof(BusyFrameAnimation), new PropertyMetadata(false));}

local:BusyFrameAnimation.IsBusy="{Binding LoginIsRunning}" 属性绑定LoginIsRunning,设置LoginIsRunning值显示或隐藏等待。

<Button Content="登录"IsDefault="True"Command="{Binding LoginCommand}"local:BusyFrameAnimation.IsBusy="{Binding LoginIsRunning}"CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type pages:LoginPage}}}" HorizontalAlignment="Center"/>

 public class BoolenToVisiblityConverter : BaseValueConverter<BoolenToVisiblityConverter>{public override object Convert(object value, Type targetType, object parameter, CultureInfo culture){if (parameter == null)return (bool)value ? Visibility.Hidden : Visibility.Visible;elsereturn (bool)value ? Visibility.Visible : Visibility.Hidden;}public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotImplementedException();}}

重点部分来了,实现加载动画和旋转效果功能,先去iconfont找个等待矢量图。

<Geometry x:Key="Icon-Waiting">M60.014 542.385c0-37.982 30.385-68.367 68.367-68.367 45.578 0 75.964 30.385 75.964 68.367 0 45.578-30.385 75.964-75.964 75.964-37.982 0-68.367-30.385-68.367-75.964zM151.171 276.512v0c0-53.175 37.982-98.753 91.157-98.753s98.753 45.578 98.753 98.753v0c0 53.175-45.578 91.157-98.753 91.157s-91.157-37.982-91.157-91.157v0zM189.153 815.856v0c0-30.385 22.789-53.175 53.175-53.175s53.175 22.789 53.175 53.175v0c0 30.385-22.789 53.175-53.175 53.175s-53.175-22.789-53.175-53.175zM455.027 929.802v0c0-37.982 22.789-60.772 60.772-60.772s60.772 22.789 60.772 60.772v0c0 37.982-22.789 60.772-60.772 60.772-37.982 0-60.772-22.789-60.772-60.772zM751.287 815.856c0-22.789 15.193-37.982 37.982-37.982s37.982 15.193 37.982 37.982c0 22.789-15.193 37.982-37.982 37.982-22.789 0-37.982-15.193-37.982-37.982zM834.847 542.385c0-30.385 30.385-60.772 68.367-60.772 30.385 0 60.772 30.385 60.772 60.772 0 37.982-30.385 68.367-60.772 68.367-37.982 0-68.367-30.385-68.367-68.367zM660.13 276.512c0-75.964 60.772-129.139 129.139-129.139s129.139 53.175 129.139 129.139c0 68.367-60.772 129.139-129.139 129.139-68.367 0-129.139-60.772-129.139-129.139zM386.66 162.566c0-68.367 60.772-129.139 129.139-129.139s129.139 60.772 129.139 129.139c0 68.367-60.772 129.139-129.139 129.139-68.367 0-129.139-60.772-129.139-129.139z</Geometry>

用label实现加载矢量图,PathData="{DynamicResource Icon-Waiting}",动画旋转360度和时长设置等属性,Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"From="0"To="360"Duration="0:0:2"

<Style x:Key="SpinningLabel" TargetType="{x:Type Label}"><Setter Property="RenderTransformOrigin" Value="0.5,0.5"/><Setter Property="RenderTransform"><Setter.Value><RotateTransform/></Setter.Value></Setter><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Label}"><Viewbox x:Name="IconBox" Width="{TemplateBinding FontSize}" Height="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"><Path Data="{DynamicResource Icon-Waiting}" Fill="{TemplateBinding Foreground}" Stretch="Fill"></Path></Viewbox></ControlTemplate></Setter.Value></Setter><Style.Resources><Storyboard x:Key="Spin"><DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"From="0"To="360"Duration="0:0:2"RepeatBehavior="Forever"/></Storyboard></Style.Resources><Style.Triggers><DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=IsVisible}" Value="True"><DataTrigger.EnterActions><BeginStoryboard Name="SpinStoryboard" Storyboard="{StaticResource Spin}"/></DataTrigger.EnterActions><DataTrigger.ExitActions><RemoveStoryboard BeginStoryboardName="SpinStoryboard"/></DataTrigger.ExitActions></DataTrigger></Style.Triggers></Style>

之前讲过触发有三种方式,事件触发和属性触发都使用过,这里用到数据触发功能。

<DataTriggerBinding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=IsVisible}"Value="True"> 此处代码表示当显示的时候调用Storyboard="{StaticResource Spin}"名称是上面Spin的键。

标签控件显示和旋转功能已经实现了,需要加入到按钮中。

<Style TargetType="{x:Type Button}"><Setter Property="Background" Value="{StaticResource WordOrangeBrush}"/><Setter Property="Foreground" Value="{StaticResource ForegroundLightBrush}"/><Setter Property="BorderThickness" Value="0"/><Setter Property="FontSize" Value="30"/><Setter Property="Margin" Value="0,10,0,0"/><Setter Property="Padding" Value="50,10"/><Setter Property="local:BusyFrameAnimation.IsBusy" Value="False"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ButtonBase}"><Border x:Name="border"CornerRadius="10"BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"><Grid><TextBlock Text="{TemplateBinding Content}"Visibility="{TemplateBinding local:BusyFrameAnimation.IsBusy, Converter={cv:BoolenToVisiblityConverter}}"Focusable="False"FontFamily="{TemplateBinding FontFamily}"FontSize="{TemplateBinding FontSize}"HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/><Label Style="{DynamicResource SpinningLabel}"FontSize="{TemplateBinding FontSize}"Foreground="{TemplateBinding Foreground}"HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"Visibility="{TemplateBinding local:BusyFrameAnimation.IsBusy, Converter={cv:BoolenToVisiblityConverter}, ConverterParameter=True}"/></Grid></Border><ControlTemplate.Triggers><EventTrigger RoutedEvent="MouseEnter"><BeginStoryboard><Storyboard><ColorAnimation To="{StaticResource WordBlue}" Duration="0:0:0.3" Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color"/></Storyboard></BeginStoryboard></EventTrigger><EventTrigger RoutedEvent="MouseLeave"><BeginStoryboard><Storyboard><ColorAnimation From="{StaticResource WordBlue}" Duration="0:0:0.3" Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color"/></Storyboard></BeginStoryboard></EventTrigger><Trigger Property="IsEnabled" Value="False"><Setter Property="Background" TargetName="border" Value="{StaticResource ForegroundDarkBrush}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

默认等待动画是不显示,所以设置依赖属性<SetterProperty="local:BusyFrameAnimation.IsBusy"Value="False"/>

当Visibility="{TemplateBinding local:BusyFrameAnimation.IsBusy, Converter={cv:BoolenToVisiblityConverter}, ConverterParameter=True}" 转换类型cv:BoolenToVisiblityConverter和设置依赖属性BusyFrameAnimation.IsBusy=true时就会显示等待动画。

最后登录按钮绑定命令是异步等待,这里我设置显示等待10秒。

public ICommand LoginCommand{get{return new DelegateCommand(async parameter =>{await RunCommandAsync(() => this.LoginIsRunning, async () =>{await Task.Delay(10000);});});}}

RunCommandAsync异步方法,参数updatingFlag是LoginIsRunning传的值, updatingFlag.SetPropertyValue(true);显示动画,await action();等待时间后再设置false,隐藏动画效果,显示Button默认文本内容

protected async Task RunCommandAsync(Expression<Func<bool>> updatingFlag, Func<Task> action){lock (updatingFlag){if (updatingFlag.GetPropertyValue())return;updatingFlag.SetPropertyValue(true);}try{await action();}finally{updatingFlag.SetPropertyValue(false);}}

WPF UI框架界面开发教程(七)相关推荐

  1. WPF UI框架界面开发教程(五)

    先看一下登录按钮效果 源码下载地址:https://download.csdn.net/download/liaohaiyin/20607269 按钮自定义样式代码 WPF 触发器有三种,分别是 Tr ...

  2. WPF UI框架界面开发教程(十二)

    为了配合界面统一风格,在样式中添加单选按钮,RadioButton选中后,Background变成蓝色,圆角给个1000. 在样式中先添加两列,第一列显示是否选中单选按钮,而且给的高度和宽度都是20, ...

  3. wpf ui框架_RapidCAX 开源UI框架

    微信公众号:AnyCAD专注打造新一代图形平台,助每一个工业软件成功! RapidCAX UI框架 从零开始搭建CAD/CAE/CAM的UI框架是一件繁琐的事情:需要选组件.集成组件以及各种配置.若集 ...

  4. uni-app uView UI框架 下载安装教程

    uviewUI 多平台快速开发的UI框架 uni-app2018年初发布以来,一直蓬勃发展,一派欣欣向荣,社区也是人声鼎沸,众望所归. 因此,uView应运而生,uView的目标是成为uni-app生 ...

  5. android的webView的教程,Android WebView 应用界面开发教程

    WebView组件本身就是一个浏览器实现,Android5.0增强的WebView基于Chromium M37,直接支持WebRTC.WebAudio.WebGL.开发者可以直接在WebView中使用 ...

  6. 鸿蒙系统,鸿蒙app简易登录界面,界面开发教程

    鸿蒙系统,鸿蒙app简易登录界面,界面开发教程. // 这个是主Ability public class MainAbilitySlice extends AbilitySlice {@Overrid ...

  7. python图形化界面教程_python图形化界面开发教程

    python图形化界面开发教程内容摘要 python图形化界面开发教程白萝卜:泰兴电工教程,白了点,白兰地是在红葡萄酒的基础.基金从业资格教程学校,白开水.苜蓿干草.提摩西干草.兔粮方法:白居易< ...

  8. 【HTML③】JavaScript基础、使用JavaScript制作网页特效、使用前端库及UI框架快速开发

    [HTML③]JavaScript基础.使用JavaScript制作网页特效.使用前端库及UI框架快速开发 八.JavaScript基础 1.JavaScript JavaScript简称JS是用于制 ...

  9. java metronic_不懂前端的程序员不是好美工——UI框架metronic使用教程——程序员视角...

    本着不懂前端的程序员不是好美工的观点,所以作为一个仅懂一点前端的程序员,为了成为一个好美工,所以只能用些取巧的方法伪装一下. metronic一个基于bootstrap的响应式的后台管理平台的UI框架 ...

最新文章

  1. 数据库存储引擎大揭秘,不看不知道这里面的骚操作可真多!
  2. 有哪些适合远程办公的软件值得推荐?
  3. java中的System.out.print()与System.out.println()的区别
  4. 【转】节点预测与边预测任务实践
  5. 【Qt】Qt5.12编译MySQl5.7驱动(在线亲自指导)
  6. 超详细Gitlab Runner环境配置中文教程
  7. mysql判断表字段或索引是否存在,然后修改
  8. 2602 最短路径问题
  9. 数论基础(浅谈数论的部分实现)
  10. 华为防火墙重启_华为USG6000系列防火墙重置密码
  11. 居民配电所智能辅助监控系统
  12. python 高等数学实验,高等数学以及Python 实现
  13. 微信小程序生命周期笔记
  14. day01.我们为什么要学习进制
  15. 127.0.0.1是什么地址?localhost呢?
  16. Kotlin版 极简 干货集中营 APP
  17. 原创小说 - 爱人失踪(连载 中部)
  18. MLOps极致细节:18. Azure ML Pipeline(机器学习管道),Azure Container Instances (ACI)部署模型
  19. 深度学习(20):nerf论文翻译与学习
  20. 用CSS画三角形、圆、圆角

热门文章

  1. Clickhouse CTE 支持
  2. android button 中文字位置设置,iOS开发-- 设置UIButton的文字显示位置、字体的大小、字体的颜色...
  3. 微商副业卖啥东西好?兼职微商能卖什么东西?微商怎么选品?
  4. 图片版权困扰,那就用这种无版权、高清免费图片素材吧
  5. 浅谈跨境电商运行模式
  6. 解决Vmware虚拟机偶尔黑屏
  7. php 获取去年今日,描写去年今日句子 去年的今天怎么表达
  8. 蓝桥杯———数字三角形(JAVA)
  9. 墨天轮2021年度数据库获奖名单
  10. 有什么牌子台灯性价比高?性价比最高的护眼台灯