【WPF】BusyIndicator做Loading遮罩层

简介: 原文:【WPF】BusyIndicator做Loading遮罩层 百度了一下,粗略看了几个国内野人的做法,花了时间看下去感觉不太好用(比如有Loading居然只是作为窗体的一个局部控件的,没法全屏遮罩,那要你有何用?),于是谷歌找轮子去。
原文: 【WPF】BusyIndicator做Loading遮罩层

百度了一下,粗略看了几个国内野人的做法,花了时间看下去感觉不太好用(比如有Loading居然只是作为窗体的一个局部控件的,没法全屏遮罩,那要你有何用?),于是谷歌找轮子去。

好用的轮子:http://wpftoolkit.codeplex.com/wikipage?title=BusyIndicator

引入DLL(在官网或者Nuget里下载)、引入名称空间等步骤根据官方的文档来操作就好了,很简单。

测试如下:
前台代码 MainWindow.xaml:

<Window x:Class="WpfApplication1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">

    <!-- 如有需要,可以引入样式资源 -->
    <!--<Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Style/LoadingMaskStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>-->

    <StackPanel VerticalAlignment="Center">

        <xctk:BusyIndicator x:Name="_busyIndicator" IsBusy="False" 
                            BusyContent="少女祈祷中..." Background="Red">
            <!--<xctk:BusyIndicator.OverlayStyle>
                <Style TargetType="Rectangle">
                    <Setter Property="Fill" Value="#ffffeeee"/>
                </Style>
            </xctk:BusyIndicator.OverlayStyle>-->
            <!--<xctk:BusyIndicator.ProgressBarStyle>
                <Style TargetType="ProgressBar">
                    <Setter Property="Visibility" Value="Collapsed"/>
                </Style>
            </xctk:BusyIndicator.ProgressBarStyle>-->

            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Button Click="Show" Content="LLLL" Height="40" Width="60"/>
                <Button Click="Show" Content="LLLL" Height="40" Width="60"/>
                <Button x:Name="btn" Click="btn_OnClick" Content="测试" Height="40" Width="60"/>
                <Button Click="Show" Content="RRRR" Height="40" Width="60"/>
                <Button Click="Show" Content="RRRR" Height="40" Width="60"/>
            </StackPanel>
        </xctk:BusyIndicator>
    </StackPanel>
</Window>

对应的后台代码 MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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 WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btn_OnClick(object sender, RoutedEventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();
            //this is where the long running process should go
            worker.DoWork += (o, ea) =>
            {
                //no direct interaction with the UI is allowed from this method
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(100);
                }
            };
            worker.RunWorkerCompleted += (o, ea) =>
            {
                //work has completed. you can now interact with the UI
                _busyIndicator.IsBusy = false;
            };
            //set the IsBusy before you start the thread
            _busyIndicator.IsBusy = true;
            worker.RunWorkerAsync();
        }

        private void Show(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("还能点!");
        }
    }
}

运行效果如下:
这里写图片描述

注意点:

  • 想要这个BusyIndicator全屏遮罩,需要把它作为这个Window的直接子节点。而这个BusyIndicator控件自身也只能包含一个子节点,所以可用一个Grid或StackPanel标签做包裹。
  • 官方文档中没有说到BusyIndicator的XMAL全屏遮罩写法,我是看youtube这个小哥这么写的:

https://www.youtube.com/watch?v=1h_mLA-eE40


2016.12.29下午更新:

发现一个问题,当在worker.DoWork委托中执行的操作需要修改UI时,会发生运行时异常:

Additional information: 该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。

谷歌一下:
http://stackoverflow.com/questions/18331723/this-type-of-collectionview-does-not-support-changes-to-its-sourcecollection-fro
这里写图片描述

意思是说,UI是由UI线程创建并维护的,BackgroundWorker对象作为一个新建的子线程,无法跨线程操作UI(这点跟Android很像嘛),想要跨线程操作UI,需要使用Dispatcher分发器机制。所以worker.DoWork的代码修改一下就好了:

worker.DoWork += (o, ea) =>
{
    //no direct interaction with the UI is allowed from this method
    // 不需要操作UI的代码
    // ...

    // 需要操作UI的代码
    App.Current.Dispatcher.Invoke((Action)delegate
    {
        // 如MVVM中其他Controller、ViewModel中操作UI的方法
        designController.Initialize();
        webImageViewModel.UpdateImages(designId);
    });
};

重要参考:

https://elegantcode.com/2009/07/03/wpf-multithreading-using-the-backgroundworker-and-reporting-the-progress-to-the-ui/
https://elegantcode.com/2011/10/07/extended-wpf-toolkitusing-the-busyindicator/ 最后一个例子有提及Dispatcher
https://vkishorekumar.wordpress.com/2011/07/18/what-is-thread-affinity/ 报错原因:线程的紧密性(亲和性?)

 

目录
相关文章
WPF 圆形Loading
原文:WPF 圆形Loading 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a771948524/article/details/9271933 ...
1141 0
|
C# 前端开发 Android开发
WPF 客户端浏览器 添加Loading加载进度
原文:WPF 客户端浏览器 添加Loading加载进度 在windows开发界面时,使用浏览器来请求和显示网页内容,是比较常见的。 但是在请求网页内容时,因网速或者前端功能复杂加载较慢,亦或者加载时遇到各种问题,如空白/黑屏/加载不完整/证书问题等。
1646 0
|
C# Windows
WPF实现炫酷Loading控件
原文:WPF实现炫酷Loading控件 Win8系统的Loading效果还是很不错的,网上也有人用CSS3等技术实现,研究了一下,并打算用WPF自定义一个Loading控件实现类似的效果,并可以让用户对Loading的颗粒(Particle)背景颜色进行自定义,话不多说,直接上代码: 1、用VS2...
1238 0
|
C#
WPF圆形环绕的Loading动画
原文:WPF圆形环绕的Loading动画 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangyisen0713/article/details/18218167 WPF制作一个模仿Silverlight页面还有win8系统的Loading动画效果,其实就用到WPF的ellipse即可,如果想要简单或者更好的效果的话还是要用Blend去做哈。
887 0
|
C#
WPF loading加载动画库
原文:WPF loading加载动画库 1. 下载Dll        https://pan.baidu.com/s/1wKgv5_Q8phWo5CrXWlB9dA 2.
2219 0
|
C#
WPF和Expression Blend开发实例:Loading动画
原文:WPF和Expression Blend开发实例:Loading动画 今天来点实际的,项目中可以真实使用的,一个Loading的动画,最后封装成一个控件,可以直接使用在项目中,先上图: 整个设计比较简单,就是在界面上画18个Path,然后通过动画改变OpacityMask的值来实现一种动态的效果.
1176 0
|
15天前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
|
4月前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
65 1
|
8月前
|
C# Windows
WPF技术之图形系列Polygon控件
WPF Polygon是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制多边形形状。它可以通过设置多个点的坐标来定义多边形的形状,可以绘制任意复杂度的多边形。
454 0
|
8月前
|
C# Windows
WPF技术之RichTextBox控件
WPF RichTextBox是Windows Presentation Foundation (WPF)中提供的一个强大的文本编辑控件,它可以显示富文本格式的文本,支持多种文本处理操作。
346 0