页面代码如下
XML
<UserControl x:Class="ShangHaiElectricalLine.Controls.LoadingAnimation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ShangHaiElectricalLine.Controls"
mc:Ignorable="d"
d:DesignHeight="200"
d:DesignWidth="200"
Background="Transparent">
<UserControl.Resources>
<!-- 不需要定义转换器资源,可以直接在绑定中使用 -->
</UserControl.Resources>
<Grid>
<!-- 毛玻璃效果 -->
<Border Background="#80FFFFFF"
CornerRadius="20"
Width="260"
Height="200"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Border.Effect>
<BlurEffect Radius="8" />
</Border.Effect>
</Border>
<Border Background="White"
CornerRadius="16"
Width="250"
Height="190"
VerticalAlignment="Center"
HorizontalAlignment="Center"
BorderThickness="1"
BorderBrush="#E3F2FD">
<StackPanel VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="20">
<!-- 渐变环形加载 -->
<Viewbox Width="70"
Height="70">
<Grid>
<!-- 背景环 -->
<Ellipse Stroke="#E3F2FD"
StrokeThickness="4" />
<!-- 动态环 -->
<Ellipse x:Name="LoadingRing"
Stroke="#2196F3"
StrokeThickness="4"
StrokeDashArray="0.5 1.5"
StrokeDashCap="Round"
StrokeDashOffset="2">
<Ellipse.RenderTransform>
<RotateTransform CenterX="35"
CenterY="35" />
</Ellipse.RenderTransform>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<!-- 旋转动画 -->
<DoubleAnimation Storyboard.TargetName="LoadingRing"
Storyboard.TargetProperty="(Ellipse.RenderTransform).(RotateTransform.Angle)"
From="0"
To="360"
Duration="0:0:1.2" />
<!-- 线头动画 -->
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="LoadingRing"
Storyboard.TargetProperty="StrokeDashOffset">
<LinearDoubleKeyFrame KeyTime="0:0:0"
Value="0" />
<LinearDoubleKeyFrame KeyTime="0:0:1.2"
Value="3" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
</Grid>
</Viewbox>
<!-- 加载文字 -->
<TextBlock Text="{Binding LoadingText, RelativeSource={RelativeSource AncestorType=UserControl}}"
Margin="0,20,0,0"
Foreground="#2196F3"
FontSize="16"
FontWeight="SemiBold"
HorizontalAlignment="Center"
TextAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="2"
Opacity="0.3"
ShadowDepth="1" />
</TextBlock.Effect>
</TextBlock>
</StackPanel>
</Border>
</Grid>
</UserControl>
对应的.cs文件
cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ShangHaiElectricalLine.Controls
{
/// <summary>
/// LoadingAnimation.xaml 的交互逻辑
/// </summary>
public partial class LoadingAnimation : UserControl, INotifyPropertyChanged
{
public LoadingAnimation()
{
InitializeComponent();
}
#region 依赖属性
// 是否激活加载动画
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register("IsActive", typeof(bool), typeof(LoadingAnimation),
new PropertyMetadata(false, OnIsActiveChanged));
public bool IsActive
{
get => (bool)GetValue(IsActiveProperty);
set => SetValue(IsActiveProperty, value);
}
private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is LoadingAnimation control)
{
control.OnPropertyChanged(nameof(IsActive));
}
}
// 加载文本
public static readonly DependencyProperty LoadingTextProperty =
DependencyProperty.Register("LoadingText", typeof(string), typeof(LoadingAnimation),
new PropertyMetadata("正在加载...", OnLoadingTextChanged));
public string LoadingText
{
get => (string)GetValue(LoadingTextProperty);
set => SetValue(LoadingTextProperty, value);
}
private static void OnLoadingTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is LoadingAnimation control)
{
control.OnPropertyChanged(nameof(LoadingText));
}
}
#endregion
#region INotifyPropertyChanged 实现
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
如何使用
1.在资源中使用
<!-- 添加转换器资源 -->
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace ShangHaiElectricalLine.Converters
{
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value is bool boolValue && boolValue) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
2. 在View中加入这个样式
XML
<!-- 加载遮罩层样式 -->
<Style x:Key="LoadingOverlayStyle"
TargetType="Border">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,1">
<GradientStop Color="#1A0D47A1"
Offset="0" />
<GradientStop Color="#800D47A1"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Visibility"
Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsLoading}"
Value="True">
<Setter Property="Visibility"
Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
在ViewModel中加入这两个属性
cs
[ObservableProperty]
private bool _isLoading;
[ObservableProperty]
private string _loadingText = "正在加载页面...";
3.使用自定义样式
XML
<!-- 加载遮罩层(在最顶层) -->
<Border Style="{StaticResource LoadingOverlayStyle}"
Panel.ZIndex="9999">
<Grid>
<!-- 使用自定义加载控件 -->
<controls:LoadingAnimation
IsActive="True"
LoadingText="{Binding LoadingText}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Border>
效果如下
