一直想实现这么个功能来着,所以去网上搜了资料,复杂的看不懂,后来挑了一个最简单的,复用了这位大神的很多代码(大神看到了别打脸)。这位大神是用UserControl,使用时则是调用用户控件中的方法。之前有用过Telerik的RadBusyIndicator,感觉很好,它是将要遮罩部分直接以内容的形式包裹在RadBusyIndicator的Content属性中,使用时就更简单了,IsBusy=true时遮层罩开启,IsBusy=false遮层罩关闭/隐藏。一为了实现起来不复杂,二为了实现RadBusyIndicator的用法,实现自己的自定义控件,所以才有了这篇文章,先上效果图

接下来先上自定义控件前台代码:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyBusyIndicator">
    
    <SolidColorBrush Color="#FF007BE5" x:Key="CirclesColor" />
    <Style TargetType="{x:Type local:BusyIndicator}">
        <Setter Property="Background" Value="#FFFFC0CB"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:BusyIndicator}">
                    <Grid>
                        <ContentControl x:Name="PART_Content" Content="{TemplateBinding Content}" />
                        <Border x:Name="PART_Border" Visibility="Hidden" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"
                                Opacity="0.5">
                            
                        </Border>
                        <Grid x:Name="PART_LayoutRoot" 
                Background="Transparent"    
                ToolTip="Please wait...."    
                HorizontalAlignment="Center"    
                VerticalAlignment="Center" Visibility="Hidden">
 
                            <TextBlock Text="Loading..."  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" Foreground="#FFE3953D" FontWeight="Bold" />
                            <Canvas RenderTransformOrigin="0.5,0.5" x:Name="PART_Canvas"
                    HorizontalAlignment="Center"    
                    VerticalAlignment="Center" Width="120"    
                    Height="120">
                                <Ellipse x:Name="PART_C0" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="1.0"/>
                                <Ellipse x:Name="PART_C1" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.9"/>
                                <Ellipse x:Name="PART_C2" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.8"/>
                                <Ellipse x:Name="PART_C3" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.7"/>
                                <Ellipse x:Name="PART_C4" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.6"/>
                                <Ellipse x:Name="PART_C5" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.5"/>
                                <Ellipse x:Name="PART_C6" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.4"/>
                                <Ellipse x:Name="PART_C7" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.3"/>
                                <Ellipse x:Name="PART_C8" Width="20" Height="20"   
                         Canvas.Left="0"    
                         Canvas.Top="0" Stretch="Fill"    
                         Fill="{StaticResource CirclesColor}" Opacity="0.2"/>
                                <Canvas.RenderTransform>
                                    <RotateTransform x:Name="PART_SpinnerRotate"   
                         Angle="0" />
                                </Canvas.RenderTransform>
                            </Canvas>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

下面的是自定义控件的后台逻辑和依赖属性:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.Windows.Threading;
 
namespace MyBusyIndicator
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
    /// 元素中: 
    ///
    ///     xmlns:MyNamespace="clr-namespace:MyBusyIndicator"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
    /// 元素中: 
    ///
    ///     xmlns:MyNamespace="clr-namespace:MyBusyIndicator;assembly=MyBusyIndicator"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
    /// 并重新生成以避免编译错误: 
    ///
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:BusyIndicator/>
    ///
    /// </summary>
    public class BusyIndicator : Control
    {
        private readonly DispatcherTimer animationTimer;
 
        public static readonly DependencyProperty IsBusyProperty;
 
        public static readonly DependencyProperty ContentProperty;
        static BusyIndicator()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BusyIndicator), new FrameworkPropertyMetadata(typeof(BusyIndicator)));
 
            IsBusyProperty = DependencyProperty.Register("IsBusy", typeof(bool), typeof(BusyIndicator), new PropertyMetadata(false, new PropertyChangedCallback(OnBusyChanged)));
 
            ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(BusyIndicator));
        }
 
        public bool IsBusy
        {
            get { return (bool)GetValue(IsBusyProperty); }
            set { SetValue(IsBusyProperty, value); }
        }
 
        public object Content 
        {
            get { return GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }
 
        private static void OnBusyChanged(DependencyObject sender,DependencyPropertyChangedEventArgs e)
        {
            BusyIndicator indicator = sender as BusyIndicator;
            if ((bool)e.NewValue == true)
            {
                indicator.Start();
            }
            else
            {
                indicator.Stop();
            }
        }
 
        public BusyIndicator()
        {
            animationTimer = new DispatcherTimer(
                DispatcherPriority.ContextIdle, Dispatcher);
            animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 90);
        }
        #region Private Methods
        private void Start()
        {
            if (this.IsInitialized)
            {
                Border border = GetTemplateChild("PART_Border") as Border;
                border.Visibility = Visibility.Visible;
                Grid grid = GetTemplateChild("PART_LayoutRoot") as Grid;
                grid.Visibility = Visibility.Visible;
                animationTimer.Tick += HandleAnimationTick;
                animationTimer.Start();
            }
            
        }
 
        private void Stop()
        {
            if (this.IsInitialized)
            {
                Border border = GetTemplateChild("PART_Border") as Border;
                Grid grid = GetTemplateChild("PART_LayoutRoot") as Grid;
                border.Visibility = Visibility.Hidden;
                grid.Visibility = Visibility.Hidden;
                animationTimer.Stop();
                animationTimer.Tick -= HandleAnimationTick;
            }
        }
 
        private void HandleAnimationTick(object sender, EventArgs e)
        {
            RotateTransform SpinnerRotate = GetTemplateChild("PART_SpinnerRotate") as RotateTransform;
            SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;
        }
 
        private void SetPosition(Ellipse ellipse, double offset,
            double posOffSet, double step)
        {
            ellipse.SetValue(Canvas.LeftProperty, 50.0
                + Math.Sin(offset + posOffSet * step) * 50.0);
 
            ellipse.SetValue(Canvas.TopProperty, 50
                + Math.Cos(offset + posOffSet * step) * 50.0);
        }
 
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
 
            const double offset = Math.PI;
            const double step = Math.PI * 2 / 10.0;
 
            Ellipse C0 = GetTemplateChild("PART_C0") as Ellipse;
            Ellipse C1 = GetTemplateChild("PART_C1") as Ellipse;
            Ellipse C2 = GetTemplateChild("PART_C2") as Ellipse;
            Ellipse C3 = GetTemplateChild("PART_C3") as Ellipse;
            Ellipse C4 = GetTemplateChild("PART_C4") as Ellipse;
            Ellipse C5 = GetTemplateChild("PART_C5") as Ellipse;
            Ellipse C6 = GetTemplateChild("PART_C6") as Ellipse;
            Ellipse C7 = GetTemplateChild("PART_C7") as Ellipse;
            Ellipse C8 = GetTemplateChild("PART_C8") as Ellipse;
 
            SetPosition(C0, offset, 0.0, step);
            SetPosition(C1, offset, 1.0, step);
            SetPosition(C2, offset, 2.0, step);
            SetPosition(C3, offset, 3.0, step);
            SetPosition(C4, offset, 4.0, step);
            SetPosition(C5, offset, 5.0, step);
            SetPosition(C6, offset, 6.0, step);
            SetPosition(C7, offset, 7.0, step);
            SetPosition(C8, offset, 8.0, step);
 
            if (this.IsBusy)
            {
                this.Start();
            }
            else
            {
                this.Stop();
            }
        }
 
        #endregion   
    }
}

以上便是全部控件的代码了,为了能够使用它,我将他单独编译成了一个dll,下面是如何使用该控件的例子,前台代码如下:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CustomControls"
        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
        xmlns:System="clr-namespace:System;assembly=mscorlib" x:Class="CustomControls.MainWindow"
        xmlns:my="clr-namespace:MyBusyIndicator;assembly=MyBusyIndicator"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <my:BusyIndicator x:Name="busy">
            <my:BusyIndicator.Content>
                <Grid>
                    <DataGrid>
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="第一列"/>
                            <DataGridTextColumn Header="第二列"/>
                            <DataGridTextColumn Header="第三列"/>
                        </DataGrid.Columns>
                    </DataGrid>
                </Grid>
            </my:BusyIndicator.Content>
        </my:BusyIndicator>
        <Button Content="Button" HorizontalAlignment="Right"  VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    </Grid>
</Window>

记得注意引用的命名空间和程序集,下面是后台代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 CustomControls
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            busy.IsBusy = !busy.IsBusy;
        }
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            busy.IsBusy = true;
        }
    }
}

OK,全部代码都已上。简单的说一句,不怎么会使用CSDN,不知道怎么插入代码,所以只好选择全部复制,一个很简单的控件。

WPFLoading遮层罩的更多相关文章

  1. JQuery插件:遮罩+数据加载中。。。(特点:遮你想遮,罩你想罩)

    在很多项目中都会涉及到数据加载.数据加载有时可能会是2-3秒,为了给一个友好的提示,一般都会给一个[数据加载中...]的提示.今天就做了一个这样的提示框. 先去jQuery官网看看怎么写jQuery插 ...

  2. js弹出遮层

    <script> var docEle = function () { return document.getElementById(arguments[0]) || false; } f ...

  3. WPF 蒙层罩,正在加载

    参考园子里的一篇文章,比较好用.可以直接用,可以自己改. 动画效果: 容器的触发器,旋转容器: 属性配置:使用依赖属性,并且在xaml中写绑定.

  4. 《Spring 3.x 企业应用开发实战》目录

    图书信息:陈雄华 林开雄 编著 ISBN 978-7-121-15213-9 概述: 第1章:对Spring框架进行宏观性的概述,力图使读者建立起对Spring整体性的认识. 第2章:通过一个简单的例 ...

  5. VS中的 MD/MT设置 【转】

    VS系列工具作为目前微软主打的集成开发环境,在历经了近20多年的发展后,到如今已经可以 说是Windows平台上各种IDE环境中的翘楚了.很多别的开发工具已经难望其项背了,如今VS2010也已经面市很 ...

  6. 纯CSS实现柱形图

    CSS在处理排版之强大,没有做不到,只有想不到.下面我们将一同实现一个柱状图. 先打好一个具体的框架.我们利用无序列表做整体,里面的东西我们根本选择内联无素span,strong,em来填充. < ...

  7. Metronic 使用到的开源插件汇总

    Metronic 是一套完整的 UI 模板,但不仅仅是模板,更应该说是一个 UI 框架.它除了提供了大量网页模板,也提供了非常多的 UI 组件,并且应用了众多 jQuery 插件.通过这些资源的整合, ...

  8. 150个JS特效脚本

    收集了其它一些不太方便归类的JS特效,共150个,供君查阅. 1. simplyScroll simplyScroll这个jQuery插件能够让任意一组元素产生滚动动画效果,可以是自动.手动滚动,水平 ...

  9. Android刮刮卡自定义控件

    网上的都是自己绘制的或者图片,我的需求是可以随意的自定义底部和顶部的布局.所以自己重写一个,原理就是直接继承 View 来实现一个刮层,让这个刮层和图片以及文字不产生任何依赖,再结合 FrameLay ...

随机推荐

  1. React-Native系列Android——Touch事件原理及状态效果

    Native原生相比于Hybrid或H5最大长处是具有流畅和复杂的交互效果,触摸事件便是当中重要一项,包括点击(Click).长按(LongClick).手势(gesture)等. 以最简单常见的点击 ...

  2. win64 QT(VS2013) 配置 CGAL+libQGLViewer

    网上讲的都不是太全 我来说说把~ 首先感谢这位大神: chenwk891:http://blog.csdn.net/chenwk891/article/details/42171495#reply 还 ...

  3. [springMVC - 1A] - Request processing failed; nested exception is org.apache.ibatis.builder.IncompleteElementException

    一月 14, 2016 1:30:07 下午 org.apache.catalina.core.StandardWrapperValve invoke严重: Servlet.service() for ...

  4. 请问大家ndk中LOCAL_SHARED_LIBRARIES LOCAL_LDLIBS什么区别

    请问大家ndk中LOCAL_SHARED_LIBRARIES LOCAL_LDLIBS什么区别啊 我先是编译了一个.so 然后在此次编译的使用调用,请问用LOCAL_SHARED_LIBRARIES和 ...

  5. 关于天津中软国际ETC培训中心的见与闻

    半个月的时间转眼即逝,在中软国际天津ETC的实训的两个星期就这样过去了,在中软国际天津站的这段时间也收获了非常多.明确了非常多,了解了很多关于社会就业的知识以及关于软件培训的一些事情.尽管我的了解可能 ...

  6. 【PPT】PPT倒计时动画的制作方法 5.4.3.2.1...

    制作步骤: 1.输入数字 在PPT空白页面中插入横排文本框,输入数字54321,并修改数字字体和大小. 2.修改数字的间距,让数字重叠在一起 字体间距 - 其他间距 - 紧缩 - 输入 150 3.选 ...

  7. ConfigurationManager读取dll的配置文件

    ConfigurationManager读取dll的配置文件 最近一个项目,需要发布dll给第三方使用,其中需要一些配置参数. 我们知道.NET的exe工程是自带的App.config文件的,编译之后 ...

  8. thinkphp 3.2多语言设置

    1.将CheckLangBehavior.class.php(没有的话去下载完整版)文件放到此目录下:\ThinkPHP\Extend\Behavior 2.修改目录下文件Application\Ho ...

  9. swift2.0中文版教程

    有些同学问我要swift的中文版教程,为了节省大家的找资料的时间,我就把我网上下载的PDF放到这里共享好了. 点击链接或者右击选择下载文件进行下载:swift2.0中文版教程 在此也感谢翻译者们的贡献 ...

  10. SQL Server Profiler 跟踪sql小技巧

    使用Profile监控sql时候经常会有很多很多的sql,想查询那条是自己的sql很困难,但是连接字串有个参数可以解决这个问题这个参数是Application Name例如说 我们在需要的数据库连接中 ...