项目中用到不少后台数据请求需要前端等待,添加加载动画改善用户体验
一、动画界面制作
添加一个自定义控件
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomCtrlLib">
<Storyboard x:Key="StoryLeftToRight" RepeatBehavior="Forever" Duration="00:00:01.50">
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C0"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="1.0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C1"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.9" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C2"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.8" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C3"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.7" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C4"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.6" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C5"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C6"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.4" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C7"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.3" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C8"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="C9"
Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="0.1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.15" Value="1.0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.30" Value="0.9" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0.8" />
<SplineDoubleKeyFrame KeyTime="00:00:00.60" Value="0.7" />
<SplineDoubleKeyFrame KeyTime="00:00:00.75" Value="0.6" />
<SplineDoubleKeyFrame KeyTime="00:00:00.90" Value="0.5" />
<SplineDoubleKeyFrame KeyTime="00:00:01.05" Value="0.4" />
<SplineDoubleKeyFrame KeyTime="00:00:01.20" Value="0.3" />
<SplineDoubleKeyFrame KeyTime="00:00:01.35" Value="0.2" />
<SplineDoubleKeyFrame KeyTime="00:00:01.50" Value="0.1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Style TargetType="{x:Type local:LoadingView}">
<Setter Property="Template">
<Setter.Value>
<!--控件模板-->
<ControlTemplate TargetType="{x:Type local:LoadingView}">
<StackPanel VerticalAlignment="Center">
<Canvas RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center" Width="120" Height="120">
<Canvas.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource StoryLeftToRight}" />
</EventTrigger>
</Canvas.Triggers>
<Ellipse x:Name="C0" Width="20" Height="20" Canvas.Left="50" Canvas.Top="0" Stretch="Fill" Fill="#D8C5A5" Opacity="1.0"/>
<Ellipse x:Name="C1" Width="20" Height="20" Canvas.Left="20.61073738537635" Canvas.Top="9.54915028125263" Stretch="Fill" Fill="#D8C5A5" Opacity="0.9"/>
<Ellipse x:Name="C2" Width="20" Height="20" Canvas.Left="2.447174185242325" Canvas.Top="34.549150281252622" Stretch="Fill" Fill="#D8C5A5" Opacity="0.8"/>
<Ellipse x:Name="C3" Width="20" Height="20" Canvas.Left="2.4471741852423179" Canvas.Top="65.450849718747364" Stretch="Fill" Fill="#D8C5A5" Opacity="0.7"/>
<Ellipse x:Name="C4" Width="20" Height="20" Canvas.Left="20.610737385376332" Canvas.Top="90.450849718747364" Stretch="Fill" Fill="#D8C5A5" Opacity="0.6"/>
<Ellipse x:Name="C5" Width="20" Height="20" Canvas.Left="50" Canvas.Top="100" Stretch="Fill" Fill="#D8C5A5" Opacity="0.5"/>
<Ellipse x:Name="C6" Width="20" Height="20" Canvas.Left="79.389262614623647" Canvas.Top="90.450849718747378" Stretch="Fill" Fill="#D8C5A5" Opacity="0.4"/>
<Ellipse x:Name="C7" Width="20" Height="20" Canvas.Left="97.552825814757682" Canvas.Top="65.450849718747392" Stretch="Fill" Fill="#D8C5A5" Opacity="0.3"/>
<Ellipse x:Name="C8" Width="20" Height="20" Canvas.Left="97.552825814757682" Canvas.Top="34.549150281252643" Stretch="Fill" Fill="#D8C5A5" Opacity="0.2"/>
<Ellipse x:Name="C9" Width="20" Height="20" Canvas.Left="79.389262614623675" Canvas.Top="9.5491502812526363" Stretch="Fill" Fill="#D8C5A5" Opacity="0.1"/>
<Canvas.RenderTransform>
<RotateTransform x:Name="SpinnerRotate" Angle="0" />
</Canvas.RenderTransform>
</Canvas>
<TextBlock Text="{TemplateBinding Message}" HorizontalAlignment="Center" FontSize="30" Foreground="#D8C5A5" Margin="0,10,0,0"></TextBlock>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
对应类定义,添加了一个依赖属性,可让用户自定义加载时显示的文本
using System.Windows;
using System.Windows.Controls;
namespace CustomCtrlLib
{
/// <summary>
/// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
///
/// Step 1a) Using this custom control in a XAML file that exists in the current project.
/// Add this XmlNamespace attribute to the root element of the markup file where it is
/// to be used:
///
/// xmlns:MyNamespace="clr-namespace:CustomCtrlLib"
///
///
/// Step 1b) Using this custom control in a XAML file that exists in a different project.
/// Add this XmlNamespace attribute to the root element of the markup file where it is
/// to be used:
///
/// xmlns:MyNamespace="clr-namespace:CustomCtrlLib;assembly=CustomCtrlLib"
///
/// You will also need to add a project reference from the project where the XAML file lives
/// to this project and Rebuild to avoid compilation errors:
///
/// Right click on the target project in the Solution Explorer and
/// "Add Reference"->"Projects"->[Select this project]
///
///
/// Step 2)
/// Go ahead and use your control in the XAML file.
///
/// <MyNamespace:CustomControl1/>
///
/// </summary>
public class LoadingView : Control
{
static LoadingView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(LoadingView), new FrameworkPropertyMetadata(typeof(LoadingView)));
}
public static readonly DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(LoadingView));
/// <summary>
/// 默认文本
/// </summary>
public string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty, value); }
}
}
}
二、使用时可以在最外层加个遮罩,在后台设置Loading的值来控制动画是否显示
<!--Loading Mask-->
<Border Grid.RowSpan="2" Visibility="{Binding Path=Loading, Mode=TwoWay}" HorizontalAlignment="Stretch" Background="#004B64" Opacity="0.3" IsEnabled="False"
VerticalAlignment="Stretch">
<CustomLib:LoadingView Message="Loading"></CustomLib:LoadingView>
</Border>
三、prism中module间通信
项目中是一个主窗口里开tab页方式,如果是tab中界面加载时,动画是要遮住整个主窗口的,这样遮罩定义只能放在主窗口中,就需要在tab界面中将是否显示传递给主窗口。项目使用的是prism框架,在这使用Event Aggregation事件聚合实现。
添加一个事件供发布订阅,参数是bool类型
public class LoadingSentEvent : PubSubEvent<bool>
{
}
在主窗口订阅事件
private Visibility _loading = Visibility.Collapsed;
public Visibility Loading
{
get { return _loading; }
set { SetProperty(ref _loading, value); }
}
IEventAggregator _eventAggregator;
public MainWindowViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<LoadingSentEvent>().Subscribe(LoadingReceived);
}
private void LoadingReceived(bool flag)
{
if (flag)
Loading = Visibility.Visible;
else
Loading = Visibility.Collapsed;
}
在需要的页面发布事件
readonly IEventAggregator _eventAggregator;
_eventAggregator.GetEvent<LoadingSentEvent>().Publish(true); //显示加载界面
_eventAggregator.GetEvent<LoadingSentEvent>().Publish(false); //隐藏加载界面