直接上代码!
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Media.Effects; using System.Windows.Threading; namespace SoftRGB.Controls { [TemplateVisualState(Name = "Indicating", GroupName = "IndicatorStates")] [TemplateVisualState(Name = "Free", GroupName = "IndicatorStates")] public class ProgressIndicator : Control { static ProgressIndicator() { DefaultStyleKeyProperty.OverrideMetadata(typeof(ProgressIndicator), new FrameworkPropertyMetadata(typeof(ProgressIndicator))); } public ProgressIndicator() { } #region 依赖属性 public static readonly DependencyProperty IsIndicatingProperty = DependencyProperty.Register("IsIndicating", typeof(bool), typeof(ProgressIndicator), new PropertyMetadata(false, new PropertyChangedCallback(OnIsIndicatingChanged))); static void OnIsIndicatingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { ProgressIndicator indicator = sender as ProgressIndicator; if (indicator == null) return; indicator.UpdateStates(); } public static readonly DependencyProperty IsIndeterminateProperty = DependencyProperty.Register("IsIndeterminate", typeof(bool), typeof(ProgressIndicator), new PropertyMetadata(true)); public static readonly DependencyProperty ProgressProperty = DependencyProperty.Register("Progress", typeof(double), typeof(ProgressIndicator), new PropertyMetadata(0d)); public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(ProgressIndicator), new PropertyMetadata(string.Empty)); public static readonly DependencyProperty BackgroundOpacityMaskProperty = DependencyProperty.Register("BackgroundOpacityMask", typeof(Brush), typeof(ProgressIndicator), new PropertyMetadata()); /// <summary> /// 获取或设置指示标题 /// </summary> public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } } /// <summary> /// 获取或设置指示进度0到1之间 /// </summary> public double Progress { get { return (double)GetValue(ProgressProperty); } set { SetValue(ProgressProperty, value); } } /// <summary> /// 获取或设置指示器是否是指示状态 /// </summary> public bool IsIndicating { get { return (bool)GetValue(IsIndicatingProperty); } set { SetValue(IsIndicatingProperty, value); } } /// <summary> /// 获取或设置指示器是否是无确定进度状态 /// </summary> public bool IsIndeterminate { get { return (bool)GetValue(IsIndeterminateProperty); } set { SetValue(IsIndeterminateProperty, value); } } /// <summary> /// 获取或设置背景透明蒙版 /// </summary> public Brush BackgroundOpacityMask { get { return (Brush)GetValue(BackgroundOpacityMaskProperty); } set { SetValue(BackgroundOpacityMaskProperty, value); } } #endregion public override void OnApplyTemplate() { base.OnApplyTemplate(); UpdateStates(false); } /// <summary> /// 更新State /// </summary> /// <param name="useTransitions"></param> void UpdateStates(bool useTransitions = true) { VisualStateManager.GoToState(this, IsIndicating ? "Indicating" : "Free", useTransitions); } } }
<Style TargetType="{x:Type local:ProgressIndicator}"> <Setter Property="Focusable" Value="False"/> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="VerticalAlignment" Value="Stretch"/> <Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="BackgroundOpacityMask" Value="#AAFFFFFF"/> <Setter Property="Background" Value="#AA000000"/> <Setter Property="Foreground" Value="White"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ProgressIndicator}"> <Grid x:Name="Root" Background="Transparent" Visibility="Collapsed" IsHitTestVisible="False"> <Grid.Resources> <SolidColorBrush x:Key="WindowOutterBorderBrush" Color="#FF656D75"/> <SolidColorBrush x:Key="WindowInnerBorderBrush" Color="White"/> <LinearGradientBrush x:Key="WindowBackgroundBrush" EndPoint="60,0" StartPoint="0,40" MappingMode="Absolute" SpreadMethod="Repeat"> <GradientStop Color="#FFD4D4D4"/> <GradientStop Color="#FFE2E2E2" Offset="0.974"/> <GradientStop Color="#FFD0D0D0" Offset="0.797"/> <GradientStop Color="#FFD9D9D9" Offset="0.302"/> <GradientStop Color="#FFE0E0E0" Offset="0.341"/> <GradientStop Color="#FFE1E1E1" Offset="0.556"/> <GradientStop Color="#FFE2E2E2" Offset="0.672"/> <GradientStop Color="#FFDDDDDD" Offset="0.823"/> <GradientStop Color="#FFE1E1E1" Offset="0.616"/> <GradientStop Color="#FFD2D2D2" Offset="1"/> </LinearGradientBrush> </Grid.Resources> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="IndicatorStates"> <VisualState x:Name="Indicating"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Visible}"/> </ObjectAnimationUsingKeyFrames> <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="IsHitTestVisible"> <DiscreteBooleanKeyFrame KeyTime="0" Value="True"/> </BooleanAnimationUsingKeyFrames> <DoubleAnimation Storyboard.TargetProperty="Opacity" BeginTime="0:0:0.5" Duration="0:0:0.2" To="1" Storyboard.TargetName="OutBorder" /> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Storyboard.TargetName="Ellipse1" BeginTime="0:0:1.5" Duration="0:0:0.5"/> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Storyboard.TargetName="Ellipse2" BeginTime="0:0:1" Duration="0:0:0.5"/> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Storyboard.TargetName="Ellipse3" BeginTime="0:0:0.5" Duration="0:0:0.5"/> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Storyboard.TargetName="Ellipse4" BeginTime="0:0:0" Duration="0:0:0.5"/> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse1" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="45" /> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse1" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:1.5" Storyboard.TargetName="Ellipse2" > <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse2" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="45"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse2" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:1.5" Storyboard.TargetName="Ellipse3" > <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:1.5" Storyboard.TargetName="Ellipse3"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse3" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="45"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse3" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="45"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:1.5" Storyboard.TargetName="Ellipse4" > <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:1.5" Storyboard.TargetName="Ellipse4"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse4" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" BeginTime="0:0:1.5" Duration="0:0:2" Storyboard.TargetName="Ellipse4" RepeatBehavior="Forever"> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:0.5" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1" Value="0"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:1.5" Value="45"/> <EasingDoubleKeyFrame EasingFunction="{StaticResource ExponentialEaseOut}" KeyTime="0:0:2" Value="45"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Free"> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Border x:Name="OutBorder" BorderThickness="0" Background="{TemplateBinding BackgroundOpacityMask}" Opacity="0" > <Grid VerticalAlignment="Center" HorizontalAlignment="Center" MinWidth="220" > <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Canvas x:Name="Canvas_Loading" Width="65" Height="65" > <Ellipse x:Name="Ellipse1" Width="20" Height="20" Fill="#ffee4e69" Canvas.Left="0" Canvas.Top="0" Opacity="0" /> <Ellipse x:Name="Ellipse2" Width="20" Height="20" Fill="#ff985fe5" Canvas.Left="45" Canvas.Top="0" Opacity="0" /> <Ellipse x:Name="Ellipse3" Width="20" Height="20" Fill="#ff70a7f1" Canvas.Left="45" Canvas.Top="45" Opacity="0" /> <Ellipse x:Name="Ellipse4" Width="20" Height="20" Fill="#fff7d653" Canvas.Left="0" Canvas.Top="45" Opacity="0" /> </Canvas> <Border Grid.Row="1" Margin="0,10,0,0" BorderThickness="0" CornerRadius="10" Background="{TemplateBinding Background}" Padding="10,4" HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Text="{TemplateBinding Title}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" /> <TextBlock Grid.Column="1" Margin="10,0,0,0" Visibility="{Binding IsIndeterminate, RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource BoolReversalToVisibilityConverter}}" Text="{Binding Progress, RelativeSource={RelativeSource TemplatedParent},StringFormat=P0}" /> </Grid> </Border> </Grid> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
使用: <RGBCtrl:ProgressIndicator x:Name="ProgressIndicatorMain" Title="请稍候..." />
设置 ProgressIndicatorMain.IsIndicating = true; 进入加载状态,
ProgressIndicatorMain.IsIndicating = false;//关掉加载状态
效果如下:
效果如下:
注意事项,这里要注意一点当程序报错时,如果没有关闭加载状态会一直显示加载状态,解决方法,是进行try catch 在expension中设置ProgressIndicatorMain.IsIndicating = false;//关掉加载状态。