直接上代码!
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;//关掉加载状态。