zoukankan      html  css  js  c++  java
  • WPF自定义控件与样式(11)-等待/忙/正在加载状态-控件实现

    一.前言

      申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接。

      本文主要有三种实现方式:

    • 简单忙碌状态控件BusyBox;
    • Win8/win10效果忙碌状态控件ProgressRing;
    • 弹出异步等待框WaitingBox;

    二.简单忙碌状态控件BusyBox

      效果图:

    通过属性"IsActive"控制控件是否启用,后台C#代码:  

     /// <summary>
        /// BusyBox.xaml 的交互逻辑
        /// </summary>
        public partial class BusyBox : UserControl
        {
            public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(BusyBox), new PropertyMetadata(false));
            /// <summary>
            /// 是否启用
            /// </summary>
            public bool IsActive
            {
                get { return (bool)GetValue(IsActiveProperty); }
                set { SetValue(IsActiveProperty, value); }
            }
    
            static BusyBox()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(BusyBox), new FrameworkPropertyMetadata(typeof(BusyBox)));
            }
        }使用了一个字体图标,触发器中实现动画显示的控制,样式代码:  
    <Style TargetType="{x:Type local:BusyBox}">
            <Setter Property="Foreground" Value="{StaticResource TextForeground}"></Setter>
            <Setter Property="Width" Value="32"></Setter>
            <Setter Property="Height" Value="32"></Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:BusyBox}">
                        <Grid VerticalAlignment="Center" HorizontalAlignment="Center" >
                            <Viewbox Stretch="Uniform"  VerticalAlignment="Center" HorizontalAlignment="Center">
                                <TextBlock Text="&#xe65f;" x:Name="FIcon" FontSize="36" Style="{StaticResource FIcon}"  RenderTransformOrigin="0.5,0.5"
                           Foreground="{TemplateBinding Foreground}">
                                    <TextBlock.RenderTransform>
                                        <RotateTransform x:Name="TransFIcon" Angle="0"/>
                                    </TextBlock.RenderTransform>
                                </TextBlock>
                            </Viewbox>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <!--激活状态-->
                            <Trigger Property="IsActive" Value="true">
                                <Setter Property="Visibility" Value="Visible" TargetName="FIcon"/>
                                <Trigger.EnterActions>
                                    <BeginStoryboard >
                                        <Storyboard >
                                            <DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetName="TransFIcon" 
                                         Storyboard.TargetProperty="Angle" To="360" Duration="0:0:2.5"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard >
                                        <Storyboard >
                                            <DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetName="TransFIcon" 
                                         Storyboard.TargetProperty="Angle" To="0" Duration="0"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>
                            <!--非激活状态-->
                            <Trigger Property="IsActive" Value="false">
                                <Setter Property="Visibility" Value="Collapsed" TargetName="FIcon"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    使用示例:  
     <CheckBox VerticalAlignment="Center" x:Name="cbActive2" IsChecked="True" Margin="5">IsActive</CheckBox>
                <core:BusyBox Width="80" Height="80" Foreground="White" Background="Red"  Margin="5"  IsActive="{Binding IsChecked ,ElementName=cbActive2}" />
                <core:BusyBox Width="30" Height="30" Foreground="White" Background="Red"  Margin="5"  IsActive="{Binding IsChecked ,ElementName=cbActive2}" />

    四.弹出异步等待框WaitingBox

    使用的是一个模式窗体,异步执行传入的操作,实现的比较简单,没有做异常处理。另外一个缺陷就是没有支持取消操作。后台C#代码:  

    /// <summary>
        /// 简单等待框
        /// </summary>
        public partial class WaitingBox : Window
        {
            public string Text { get { return this.txtMessage.Text; } set { this.txtMessage.Text = value; } }
    
            private Action _Callback;
    
            public WaitingBox(Action callback)
            {
                InitializeComponent();
                this._Callback = callback;
                this.Loaded += WaitingBox_Loaded;
            }
    
            void WaitingBox_Loaded(object sender, RoutedEventArgs e)
            {
                this._Callback.BeginInvoke(this.OnComplate, null);
            }
    
            private void OnComplate(IAsyncResult ar)
            {
                this.Dispatcher.Invoke(new Action(() =>
                {
                    this.Close();
                }));
            }
            /// <summary>
            /// 显示等待框,owner指定宿主视图元素,callback为需要执行的方法体(需要自己做异常处理)。
            /// 目前等等框为模式窗体
            /// </summary>
            public static void Show(FrameworkElement owner, Action callback, string mes = "有一种幸福,叫做等待...")
            {
                WaitingBox win = new WaitingBox(callback);
                Window pwin = Window.GetWindow(owner);
                win.Owner = pwin;
                win.Text = mes;
                var loc = owner.PointToScreen(new Point());
                win.Left = loc.X + (owner.ActualWidth - win.Width) / 2;
                win.Top = loc.Y + (owner.ActualHeight - win.Height) / 2;
                win.ShowDialog();
            }
        }

    样式代码: 
    <Window x:Class="System.Windows.WaitingBox" x:Name="wb"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
            AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="Manual"
            ShowInTaskbar="False" Background="Transparent"
            Title="WaitingBox" Height="110" Width="260">
        <Grid>
            <!--Background="{Binding Path=Background,ElementName=wb}"-->
            <Border Background="{StaticResource WaitingBoxBackground}"  Opacity="0.89" CornerRadius="1" Effect="{StaticResource WindowDropShadow}"></Border>
            <StackPanel VerticalAlignment="Center"  Orientation="Horizontal" HorizontalAlignment="Center" Margin="5">
                <TextBlock Text="&#xe65f;" x:Name="FIcon" FontSize="50" Style="{StaticResource FIcon}"  RenderTransformOrigin="0.5,0.5" Margin="3">
                    <TextBlock.RenderTransform>
                        <RotateTransform x:Name="TransFIcon" Angle="0"/>
                    </TextBlock.RenderTransform>
                </TextBlock>
                <TextBlock x:Name="txtMessage" Margin="2,10,15,10" Width="160" VerticalAlignment="Center" TextWrapping="Wrap">Loading...</TextBlock>
            </StackPanel>
        </Grid>
        <Window.Triggers>
            <EventTrigger RoutedEvent="Window.Loaded">
                <BeginStoryboard >
                    <Storyboard >
                        <DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetName="TransFIcon" 
                                         Storyboard.TargetProperty="Angle" To="360" Duration="0:0:2.5"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Window.Triggers>
    </Window>
    使用比较简单,示例:  
      WaitingBox.Show(this, () =>
                {
                    System.Threading.Thread.Sleep(3000);
                },"正在玩命的加载,请稍后...");
                var res = MessageBoxX.Question("已经完了?");
     

    引用于

    http://www.cnblogs.com/anding/p/5006279.html

  • 相关阅读:
    3、看源码MVC中的Controllr的Json方法
    2、MVC+IOC容器+ORM结合
    1、看源码MVC如何实例化控制器?
    6、UnityConfig实现AOP
    5、动态代理AOP实现-DynamicProxy模式
    1、面向切面编程
    通过js看类似C#中的回掉
    C#新开一个线程取到数据,如何更新到主线程UI上面
    2.C#自定义Attribute
    1.C#中几个简单的内置Attribute
  • 原文地址:https://www.cnblogs.com/sjqq/p/6637473.html
Copyright © 2011-2022 走看看