WPF MVVM 弹框之等待框

目录

一、效果

二、弹框主体改造

三、等待动画用户控件

四、弹窗 ViewModel 和帮助类的改造

五、使用方法和代码地址

独立观察员 2020年10月13日

之前写过一篇《WPF MVVM 模式下的弹窗》,里面实现了确认框和消息框,经过一段时间的演化,目前又新增了可显示自定义内容的弹框、可进行信息录入的弹框、以及本文将要介绍的加载等待框。

一、效果

先来看看效果,首先是其它弹框(动图):

然后是等待弹框(动图):

下面来看如何实现,当然,是在之前的基础上进行的,前一篇文章没看的话,需要先看一下,或者直接获取文末提供的代码查看。

二、弹框主体改造

首先改造的是,给右上角的 X 和底下的确认取消按钮区域的是否显示特性 Visibility 绑定了相关属性,可以控制是否显示,这样在消息框情况下可以隐藏底部按钮,在等待框情况下可以都隐藏掉。

然后是中间的主体区域,图上看不出什么变化,实际上变化还是比较大的,代码如下:

文字版:

<ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"><StackPanel Margin="5" VerticalAlignment="Center"><TextBlock FontSize="16" Text="{Binding DialogMessage, FallbackValue='是否确认操作?是否确认操作?是否确认操作?是否确认操作?是否确认操作?', TargetNullValue='是否确认操作?'}" TextWrapping="Wrap"VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="{Binding IsShowText, Converter={StaticResource VisibleConverter}, FallbackValue=Visible}"></TextBlock><ContentControl Visibility="{Binding IsShowCustom, Converter={StaticResource VisibleConverter}, FallbackValue=Collapsed}" Content="{Binding CustomContent}" HorizontalAlignment="{Binding CustomContentHorizontalAlignment, TargetNullValue=Center, Mode=OneWay}" HorizontalContentAlignment="Center" MinWidth="50"></ContentControl></StackPanel>
</ScrollViewer>

最外层使用 ScrollViewer 包裹,如果内容过多则可滚动。往里一层是 StackPanel,里面有一个 TextBlock 用于显示文本内容,还有一个 ContentControl 用于显示自定义内容(绑定一个 FrameworkElement 类型的对象)。两种内容可以分别控制显示和隐藏,也可以同时显示,本文介绍的等待框就是使用了同时显示。

三、等待动画用户控件

按照设想,等待框的动画部分作为自定义内容放入弹框的 ContentControl 中,所以我们需要新建个用户控件。(此节参考朝夕教育 Jovan 老师在 B 站发布的 WPF 教学视频的“动画实战”一节)

将一个 Grid 分为四列,每列中放置一个不同颜色的 Border (以 Grid 包裹)并设置 LayoutTransform 变换类型为 ScaleTransform,并给每个 ScaleTransform 命名:

Border 显示为圆形并居中的代码为:

<Grid.Resources><Style TargetType="Border"><Setter Property="Width" Value="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualWidth, Converter={StaticResource DivideConverter}, ConverterParameter=2}"></Setter><Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Self}, Path=Width}"></Setter><Setter Property="CornerRadius" Value="100"></Setter><!--<Setter Property="LayoutTransform"><Setter.Value><ScaleTransform ScaleX="1.6" ScaleY="1.6"></ScaleTransform></Setter.Value></Setter>-->
</Style>
</Grid.Resources>

也就是设置宽度为包裹它的 Grid 的宽度的一半,即每列宽度的一半,这个平分的操作是通过转换器 DivideConverter 实现的,具体可下载代码查看。然后,高度绑定宽度,这样就是正方形了。最后再设置圆角,就成圆形了。注释的部分是设置 LayoutTransform 变换的,具体的 ScaleTransform 变换有个 ScaleX 和 ScaleY 值,分别设置 X 和 Y 方向上的变换数值(变大为 1.6 倍),由于后面需要对这两个值设置动画,所以此处不能写死,注释掉。

动画直接在后台设置:

private void UC_Wait_OnLoaded(object sender, RoutedEventArgs e)
{RunAnimation();
}private void RunAnimation()
{//定义动画;DoubleAnimation da = new DoubleAnimation(){Duration = new Duration(TimeSpan.FromMilliseconds(1000)),To = 1.6,RepeatBehavior = RepeatBehavior.Forever,AutoReverse = true,};Task.Run(async () =>{for (int i = 0; i < 4; i++){Dispatcher.Invoke(() =>{var st = FindName($"ST{i + 1}") as ScaleTransform;st?.BeginAnimation(ScaleTransform.ScaleXProperty, da);st?.BeginAnimation(ScaleTransform.ScaleYProperty, da);});await Task.Delay(300);}});
}

界面载入后执行动画方法,动画方法中先定义了一个 DoubleAnimation 类型的动画:间隔一秒,目标值为 1.6,一直重复,自动反转。然后在循环中按照命名规则,依次先使用 FindName 方法找到 ScaleTransform 元素对象,并对其设置 X 和 Y 方向上的动画,等待 300 毫秒再设置下一个,总共四个。

四、弹窗 ViewModel 和帮助类的改造

弹窗 ViewModel 中添加了一个标识是否是等待框的属性 IsWaitDialog,在倒计时计时器里面,当是等待框时改为正计时,自然也就不会触发关闭操作,代码如下:

/// <summary>
/// 是否是等待框
/// </summary>
public bool IsWaitDialog { get; set; } = false;/// <summary>
/// 倒计时计时器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{if (IsWaitDialog){LeftTime++;}else{LeftTime--;if (LeftTime <= 0){_timer.Stop();CloseCommand.Execute(null);}}
}

在控制弹框显示隐藏的属性 IsShowDialog 的 set 方法中,当是等待框时,倒计时设为零,方便后面(上面说的)直接进行正计时:

关键是帮助方法中,新增一个弹出等待框方法:

/// <summary>
/// 弹出等待框
/// </summary>
/// <param name="vm">相关ViewModel</param>
/// <param name="message">消息内容</param>
/// <param name="action">业务方法</param>
/// <param name="title">弹窗标题</param>
/// <returns></returns>
public static async Task ShowWait(ConfirmBoxViewModel vm, string message, Func<Task> action = null, string title = "请耐心等待")
{vm.CustomContent = new UC_Wait();await Task.Run(async () =>{vm.IsMessageDialog = false;vm.IsWaitDialog = true;vm.IsShowDialog = true;vm.IsShowText = true;vm.IsShowCustom = true;vm.IsShowButton = false;vm.CustomContentHorizontalAlignment = HorizontalAlignment.Stretch.ToString();if (!string.IsNullOrWhiteSpace(message)){vm.DialogMessage = message;}if (!string.IsNullOrWhiteSpace(title)){vm.DialogTitle = title;}Console.WriteLine($"等待框就绪,业务操作开始执行...");await Task.Run(async () =>{await action?.Invoke();}).ContinueWith(_ =>{vm.IsShowDialog = false;Console.WriteLine($"业务操作执行完毕,等待框关闭.");});});
}

先将自定义内容设置为等待动画用户控件,接下来是一些显示方面的设置。

关键是如何在执行完业务方法后才关闭弹窗呢?

一开始 Func<Task> action 这个参数我用的还是 Action action,这样的话,action?.Invoke() 这里不能 await,然后 .NET Core 3.1 又不支持 action?.BeginInvoke(callback, null) 这种写法。

后来把参数类型改为 Func<Task> ,就可以 await action?.Invoke() 了,而且神奇的是,调用的地方不用修改(后面展示)。这样的话,就可以通过如下方式(ContinueWith)达到业务方法执行完成之后关闭弹窗了:

Console.WriteLine($"等待框就绪,业务操作开始执行...");await Task.Run(async () =>
{await action?.Invoke();}).ContinueWith(_ =>
{vm.IsShowDialog = false;Console.WriteLine($"业务操作执行完毕,等待框关闭.");
});

五、使用方法和代码地址

使用就比较简单了:

WaitCommand ??= new RelayCommand(o => true, async o =>
{await ConfirmBoxHelper.ShowWait(DialogVm, "正在执行业务操作...", async () =>{await Task.Delay(1000 * 10);Console.WriteLine("操作完成");});
});

代码地址:https://gitee.com/dlgcy/WPFTemplate

WPF MVVM 弹框之等待框相关推荐

  1. WPF实现背景透明磨砂,并通过HandyControl组件实现弹出等待框

    WPF实现背景透明磨砂,并通过HandyControl组件实现弹出等待框 原文:WPF实现背景透明磨砂,并通过HandyControl组件实现弹出等待框 前言:上一个版本的Winform需要改成WPF ...

  2. wpf 点击按钮弹出选择框_WPF-PopupWindow wpf右下角弹出框,通过按钮调用,类似QQ CSharp C#编程 238万源代码下载- www.pudn.com...

    文件名称: WPF-PopupWindow下载 收藏√  [ 5  4  3  2  1 ] 开发工具: C# 文件大小: 90 KB 上传时间: 2013-07-24 下载次数: 19 详细说明:w ...

  3. 学习使用Bootstrap弹出框Popover提示框样式

    学习使用Bootstrap弹出框Popover提示框样式 注意事项 弹出方向 失去焦点隐藏 禁用元素弹出提示框 data属性详解 js方法与事件 方法: 事件: 注意事项 popover提示框组件依赖 ...

  4. 案例:文件下载需求:1. 页面显示超链接 2. 点击超链接后弹出下载提示框 3. 完成图片文件下载||中文文件问题

    文件下载需求:     1. 页面显示超链接     2. 点击超链接后弹出下载提示框     3. 完成图片文件下载 * 分析:     1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示 ...

  5. 第二百四十六节,Bootstrap弹出框和警告框插件

    Bootstrap弹出框和警告框插件 学习要点: 1.弹出框 2.警告框 本节课我们主要学习一下 Bootstrap 中的弹出框和警告框插件. 一.弹出框 弹出框即点击一个元素弹出一个包含标题和内容的 ...

  6. IOS开发UI篇之──自定义加载等待框(MBProgressHUD)

    这里介绍一下网友开源的MBProgressHUD类,实现等待框, 一.网上下载  MBProgessHUD 类文件,直接导入到工程即可 二.示例分析 在我的工程中示例如下: 1)在ShowImageV ...

  7. bootstrap弹出的模态框水平垂直居中的实现

    学习javascript从入门到放弃!,这是第一篇随笔,经验不足,如有不当之处,还望指出.好了废话不多说直接切入正题吧 1.bootstrap默认的model写法: //触发模态框的button &l ...

  8. java 实现文件下载保存框_Java开发网 - 任何类型的文件下载时都会弹出文件保存框的实现(原创)...

    于 2002-12-12 11:09 :):):)任何类型的文件下载时都会弹出文件保存框的实现:(:(:( 简介: 从事WEB程序设计的朋友一定都遇到过这种情况吧,对于一些操作系统可以识别的文件类型如 ...

  9. Bootstrap:弹出框和提示框效果以及代码展示

    前言:对于Web开发人员,弹出框和提示框的使用肯定不会陌生,比如常见的表格新增和编辑功能,一般常见的主要有两种处理方式:行内编辑和弹出框编辑.在增加用户体验方面,弹出框和提示框起着重要的作用,如果你的 ...

最新文章

  1. 彻底明白IP地址——计算相关地址
  2. iOS 11开发教程(二十二)iOS11应用视图实现按钮的响应(2)
  3. zoj 1670 Jewels from Heaven
  4. mysql+monitor+下载_详解MySQL监控工具 mysql-monitor
  5. CefSharp For WPF响应页面点击事件
  6. LeetCode 2008. 出租车的最大盈利(DP)
  7. 低代码发展专访系列之二:两三年内会出现“现象级”低代码产品吗?
  8. Redis缓存异常的容错实现方法( .net)
  9. python中什么是数据驱动_携程大牛谈自动化测试里的数据驱动和关键字驱动思路的理解...
  10. 虚拟机网卡和linux bridge上tap设备的关系
  11. 手机联系人误删怎么恢复?如何找回被删除的电话联系人
  12. mediawiki mysql配置_MediaWiki 搭建与配置使用
  13. 历史的味道(美国人拍摄的1974-1978年中国)
  14. 我家乡的春夏(原创)
  15. mac 安装selenium 教程
  16. 蒙特卡罗算法的matlab实现
  17. java 8 joda time,Joda Time 使用
  18. 【一点唐城】15个未来高科技产品会让你无法想象、这些开脑洞的设计太牛了
  19. 前端上传文件保存到变量中
  20. SQLPLUS中几个常用命令

热门文章

  1. tornado 第一篇
  2. iOS-生成二维码图片【附中间带有小图标二维码】(QRCode)
  3. 详解go语言的array和slice 【二】
  4. sizeof string
  5. Spring 入门学习二之IOC
  6. chrome插件网站
  7. “芯”痛痛在系统与芯片 转型升级是历史趋势
  8. Rabbitmq~对Vhost的配置
  9. PostgreSQL 统计信息pg_statistic格式及导入导出dump_stat - 兼容Oracle
  10. Insus Binary Utility