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}" />

    三.Win8/win10效果忙碌状态控件ProgressRing

      这是网上一个开源项目里的控件,项目地址:http://mahapps.com/。不做多介绍了,效果图:

     

      后台C#代码:  

    [TemplateVisualState(Name = "Large", GroupName = "SizeStates")]
        [TemplateVisualState(Name = "Small", GroupName = "SizeStates")]
        [TemplateVisualState(Name = "Inactive", GroupName = "ActiveStates")]
        [TemplateVisualState(Name = "Active", GroupName = "ActiveStates")]
        public class ProgressRing : Control
        {
            public static readonly DependencyProperty BindableWidthProperty = DependencyProperty.Register("BindableWidth", typeof(double), typeof(ProgressRing), new PropertyMetadata(default(double), BindableWidthCallback));
    
            public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(ProgressRing), new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsActiveChanged));
    
            public static readonly DependencyProperty IsLargeProperty = DependencyProperty.Register("IsLarge", typeof(bool), typeof(ProgressRing), new PropertyMetadata(true, IsLargeChangedCallback));
    
            public static readonly DependencyProperty MaxSideLengthProperty = DependencyProperty.Register("MaxSideLength", typeof(double), typeof(ProgressRing), new PropertyMetadata(default(double)));
    
            public static readonly DependencyProperty EllipseDiameterProperty = DependencyProperty.Register("EllipseDiameter", typeof(double), typeof(ProgressRing), new PropertyMetadata(default(double)));
    
            public static readonly DependencyProperty EllipseOffsetProperty = DependencyProperty.Register("EllipseOffset", typeof(Thickness), typeof(ProgressRing), new PropertyMetadata(default(Thickness)));
    
            private List<Action> _deferredActions = new List<Action>();
    
            static ProgressRing()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(ProgressRing), new FrameworkPropertyMetadata(typeof(ProgressRing)));
                VisibilityProperty.OverrideMetadata(typeof(ProgressRing),
                                                    new FrameworkPropertyMetadata(
                                                        new PropertyChangedCallback(
                                                            (ringObject, e) =>
                                                            {
                                                                if (e.NewValue != e.OldValue)
                                                                {
                                                                    var ring = (ProgressRing)ringObject;
                                                                    //auto set IsActive to false if we're hiding it.
                                                                    if ((Visibility)e.NewValue != Visibility.Visible)
                                                                    {
                                                                        //sets the value without overriding it's binding (if any).
                                                                        ring.SetCurrentValue(ProgressRing.IsActiveProperty, false);
                                                                    }
                                                                    else
                                                                    {
                                                                        // #1105 don't forget to re-activate
                                                                        ring.IsActive = true;
                                                                    }
                                                                }
                                                            })));
            }
    
            public ProgressRing()
            {
                SizeChanged += OnSizeChanged;
            }
    
            public double MaxSideLength
            {
                get { return (double)GetValue(MaxSideLengthProperty); }
                private set { SetValue(MaxSideLengthProperty, value); }
            }
    
            public double EllipseDiameter
            {
                get { return (double)GetValue(EllipseDiameterProperty); }
                private set { SetValue(EllipseDiameterProperty, value); }
            }
    
            public Thickness EllipseOffset
            {
                get { return (Thickness)GetValue(EllipseOffsetProperty); }
                private set { SetValue(EllipseOffsetProperty, value); }
            }
    
            public double BindableWidth
            {
                get { return (double)GetValue(BindableWidthProperty); }
                private set { SetValue(BindableWidthProperty, value); }
            }
    
            public bool IsActive
            {
                get { return (bool)GetValue(IsActiveProperty); }
                set { SetValue(IsActiveProperty, value); }
            }
    
            public bool IsLarge
            {
                get { return (bool)GetValue(IsLargeProperty); }
                set { SetValue(IsLargeProperty, value); }
            }
    
            private static void BindableWidthCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                var ring = dependencyObject as ProgressRing;
                if (ring == null)
                    return;
    
                var action = new Action(() =>
                {
                    ring.SetEllipseDiameter(
                        (double)dependencyPropertyChangedEventArgs.NewValue);
                    ring.SetEllipseOffset(
                        (double)dependencyPropertyChangedEventArgs.NewValue);
                    ring.SetMaxSideLength(
                        (double)dependencyPropertyChangedEventArgs.NewValue);
                });
    
                if (ring._deferredActions != null)
                    ring._deferredActions.Add(action);
                else
                    action();
            }
    
            private void SetMaxSideLength(double width)
            {
                MaxSideLength = width <= 20 ? 20 : width;
            }
    
            private void SetEllipseDiameter(double width)
            {
                EllipseDiameter = width / 8;
            }
    
            private void SetEllipseOffset(double width)
            {
                EllipseOffset = new Thickness(0, width / 2, 0, 0);
            }
    
            private static void IsLargeChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                var ring = dependencyObject as ProgressRing;
                if (ring == null)
                    return;
    
                ring.UpdateLargeState();
            }
    
            private void UpdateLargeState()
            {
                Action action;
    
                if (IsLarge)
                    action = () => VisualStateManager.GoToState(this, "Large", true);
                else
                    action = () => VisualStateManager.GoToState(this, "Small", true);
    
                if (_deferredActions != null)
                    _deferredActions.Add(action);
    
                else
                    action();
            }
    
            private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
            {
                BindableWidth = ActualWidth;
            }
    
            private static void IsActiveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                var ring = dependencyObject as ProgressRing;
                if (ring == null)
                    return;
    
                ring.UpdateActiveState();
            }
    
            private void UpdateActiveState()
            {
                Action action;
    
                if (IsActive)
                    action = () => VisualStateManager.GoToState(this, "Active", true);
                else
                    action = () => VisualStateManager.GoToState(this, "Inactive", true);
    
                if (_deferredActions != null)
                    _deferredActions.Add(action);
    
                else
                    action();
            }
    
            public override void OnApplyTemplate()
            {
                //make sure the states get updated
                UpdateLargeState();
                UpdateActiveState();
                base.OnApplyTemplate();
                if (_deferredActions != null)
                    foreach (var action in _deferredActions)
                        action();
                _deferredActions = null;
            }
        }
    
        internal class WidthToMaxSideLengthConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value is double)
                {
                    var width = (double)value;
                    return width <= 20 ? 20 : width;
                }
    
                return null;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }

    样式代码:  

    <Style TargetType="local:ProgressRing">
            <Setter Property="Foreground" Value="White" />
            <Setter Property="IsHitTestVisible" Value="False" />
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="MinHeight" Value="20" />
            <Setter Property="MinWidth" Value="20" />
            <Setter Property="Height" Value="60" />
            <Setter Property="Width" Value="60" />
            <Setter Property="IsTabStop" Value="False" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:ProgressRing">
                        <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
                                BorderBrush="{TemplateBinding BorderBrush}">
                            <Border.Resources>
                                <Style x:Key="ProgressRingEllipseStyle" TargetType="Ellipse">
                                    <Setter Property="Opacity" Value="0" />
                                    <Setter Property="HorizontalAlignment" Value="Left" />
                                    <Setter Property="VerticalAlignment" Value="Top" />
                                </Style>
                            </Border.Resources>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="SizeStates">
                                    <VisualState x:Name="Large">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="SixthCircle"
                                                                           Storyboard.TargetProperty="Visibility">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Small" />
                                </VisualStateGroup>
                                <VisualStateGroup x:Name="ActiveStates">
                                    <VisualState x:Name="Inactive" />
                                    <VisualState x:Name="Active">
                                        <Storyboard RepeatBehavior="Forever">
                                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="Ring"
                                                                           Storyboard.TargetProperty="Visibility">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E1" Storyboard.TargetProperty="Opacity" BeginTime="0">
                                                <DiscreteDoubleKeyFrame KeyTime="0" Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E2"
                                                                           Storyboard.TargetProperty="Opacity" BeginTime="00:00:00.167">
                                                <DiscreteDoubleKeyFrame KeyTime="0"  Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E3"
                                                                           Storyboard.TargetProperty="Opacity"  BeginTime="00:00:00.334">
                                                <DiscreteDoubleKeyFrame KeyTime="0"  Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"  Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"  Value="0" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"  Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E4"
                                                                           Storyboard.TargetProperty="Opacity"  BeginTime="00:00:00.501">
                                                <DiscreteDoubleKeyFrame KeyTime="0"  Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"  Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"  Value="0" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"  Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E5"
                                                                           Storyboard.TargetProperty="Opacity"  BeginTime="00:00:00.668">
                                                <DiscreteDoubleKeyFrame KeyTime="0"  Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"  Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"  Value="0" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"  Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E6"
                                                                           Storyboard.TargetProperty="Opacity"  BeginTime="00:00:00.835">
                                                <DiscreteDoubleKeyFrame KeyTime="0"   Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.21"   Value="1" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.22"  Value="0" />
                                                <DiscreteDoubleKeyFrame KeyTime="0:0:3.47"   Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E1R"
                                                                           BeginTime="0"  Storyboard.TargetProperty="Angle">
                                                <SplineDoubleKeyFrame KeyTime="0"  Value="-110"   KeySpline="0.13,0.21,0.1,0.7" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:0.433"   Value="10"  KeySpline="0.02,0.33,0.38,0.77" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.2"  Value="93" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.617"  Value="205"  KeySpline="0.57,0.17,0.95,0.75" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.017"  Value="357"   KeySpline="0,0.19,0.07,0.72" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.783"  Value="439" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:3.217"  Value="585"   KeySpline="0,0,0.95,0.37" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E2R"
                                                                           BeginTime="00:00:00.167"   Storyboard.TargetProperty="Angle">
                                                <SplineDoubleKeyFrame KeyTime="0"  Value="-116"   KeySpline="0.13,0.21,0.1,0.7" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:0.433"   Value="4"  KeySpline="0.02,0.33,0.38,0.77" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.2"  Value="87" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.617"  Value="199"   KeySpline="0.57,0.17,0.95,0.75" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.017"  Value="351"  KeySpline="0,0.19,0.07,0.72" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.783"  Value="433" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:3.217"  Value="579"  KeySpline="0,0,0.95,0.37" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E3R"  BeginTime="00:00:00.334"
                                                                           Storyboard.TargetProperty="Angle">
                                                <SplineDoubleKeyFrame KeyTime="0"  Value="-122"  KeySpline="0.13,0.21,0.1,0.7" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:0.433"   Value="-2"  KeySpline="0.02,0.33,0.38,0.77" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.2"  Value="81" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.617"  Value="193"  KeySpline="0.57,0.17,0.95,0.75" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.017"  Value="345"  KeySpline="0,0.19,0.07,0.72" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="427" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:3.217"   Value="573"  KeySpline="0,0,0.95,0.37" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E4R"
                                                                           BeginTime="00:00:00.501"  Storyboard.TargetProperty="Angle">
                                                <SplineDoubleKeyFrame KeyTime="0"   Value="-128"   KeySpline="0.13,0.21,0.1,0.7" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:0.433"  Value="-8"  KeySpline="0.02,0.33,0.38,0.77" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.2"  Value="75" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.617"   Value="187"  KeySpline="0.57,0.17,0.95,0.75" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="339" KeySpline="0,0.19,0.07,0.72" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="421" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:3.217"  Value="567" KeySpline="0,0,0.95,0.37" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E5R"
                                                                           BeginTime="00:00:00.668" Storyboard.TargetProperty="Angle">
                                                <SplineDoubleKeyFrame KeyTime="0"  Value="-134"  KeySpline="0.13,0.21,0.1,0.7" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:0.433"  Value="-14"  KeySpline="0.02,0.33,0.38,0.77" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.2"  Value="69" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.617"  Value="181" KeySpline="0.57,0.17,0.95,0.75" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="331"  KeySpline="0,0.19,0.07,0.72" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="415" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:3.217" Value="561"  KeySpline="0,0,0.95,0.37" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E6R" BeginTime="00:00:00.835"
                                                                           Storyboard.TargetProperty="Angle">
                                                <SplineDoubleKeyFrame KeyTime="0" Value="-140"  KeySpline="0.13,0.21,0.1,0.7" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:0.433"  Value="-20"  KeySpline="0.02,0.33,0.38,0.77" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.2" Value="63" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:1.617" Value="175" KeySpline="0.57,0.17,0.95,0.75" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="325"  KeySpline="0,0.19,0.07,0.72" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="409" />
                                                <SplineDoubleKeyFrame KeyTime="0:0:3.217"  Value="555"  KeySpline="0,0,0.95,0.37" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Grid x:Name="Ring"
                                  Margin="{TemplateBinding Padding}"
                                  MaxWidth="{Binding MaxSideLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                  MaxHeight="{Binding MaxSideLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                  Visibility="Collapsed"  RenderTransformOrigin=".5,.5"   FlowDirection="LeftToRight">
    
                                <Canvas RenderTransformOrigin=".5,.5">
                                    <Canvas.RenderTransform>
                                        <RotateTransform x:Name="E1R" />
                                    </Canvas.RenderTransform>
                                    <Ellipse x:Name="E1"
                                             Style="{StaticResource ProgressRingEllipseStyle}"
                                             Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Fill="{TemplateBinding Foreground}" />
                                </Canvas>
                                <Canvas RenderTransformOrigin=".5,.5">
                                    <Canvas.RenderTransform>
                                        <RotateTransform x:Name="E2R" />
                                    </Canvas.RenderTransform>
                                    <Ellipse x:Name="E2"
                                             Style="{StaticResource ProgressRingEllipseStyle}"
                                             Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Fill="{TemplateBinding Foreground}" />
                                </Canvas>
                                <Canvas RenderTransformOrigin=".5,.5">
                                    <Canvas.RenderTransform>
                                        <RotateTransform x:Name="E3R" />
                                    </Canvas.RenderTransform>
                                    <Ellipse x:Name="E3"
                                             Style="{StaticResource ProgressRingEllipseStyle}"
                                             Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Fill="{TemplateBinding Foreground}" />
                                </Canvas>
                                <Canvas RenderTransformOrigin=".5,.5">
                                    <Canvas.RenderTransform>
                                        <RotateTransform x:Name="E4R" />
                                    </Canvas.RenderTransform>
                                    <Ellipse x:Name="E4"
                                             Style="{StaticResource ProgressRingEllipseStyle}"
                                             Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Fill="{TemplateBinding Foreground}" />
                                </Canvas>
                                <Canvas RenderTransformOrigin=".5,.5">
                                    <Canvas.RenderTransform>
                                        <RotateTransform x:Name="E5R" />
                                    </Canvas.RenderTransform>
                                    <Ellipse x:Name="E5"
                                             Style="{StaticResource ProgressRingEllipseStyle}"
                                             Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Fill="{TemplateBinding Foreground}" />
                                </Canvas>
                                <Canvas RenderTransformOrigin=".5,.5"
                                        Visibility="Collapsed"
                                        x:Name="SixthCircle">
                                    <Canvas.RenderTransform>
                                        <RotateTransform x:Name="E6R" />
                                    </Canvas.RenderTransform>
                                    <Ellipse x:Name="E6"
                                             Style="{StaticResource ProgressRingEllipseStyle}"
                                             Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                             Fill="{TemplateBinding Foreground}" />
                                </Canvas>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    使用示例:  

     <CheckBox VerticalAlignment="Center" x:Name="cbActive" Margin="5" IsChecked="True">IsActive</CheckBox>
                <core:ProgressRing Width="80" Height="80" Foreground="Red" Margin="5"  IsActive="{Binding IsChecked ,ElementName=cbActive}" />

    四.弹出异步等待框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("已经完了?");

    原文地址:https://www.cnblogs.com/anding/p/5006279.html

  • 相关阅读:
    PAT 甲级 1132 Cut Integer (20 分)
    AcWing 7.混合背包问题
    AcWing 9. 分组背包问题
    AcWing 5. 多重背包问题 II
    AcWing 3. 完全背包问题
    AcWing 4. 多重背包问题
    AcWing 2. 01背包问题
    AcWing 875. 快速幂
    AcWing 874. 筛法求欧拉函数
    AcWing 873. 欧拉函数
  • 原文地址:https://www.cnblogs.com/mqxs/p/10142474.html
Copyright © 2011-2022 走看看