?老板加薪!看我做的WPF Loading!!!
控件名:RingLoading
作者:WPFDevelopersOrg
原文鏈接: ? ?https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal
框架使用大于等于
.NET40
;Visual Studio 2022
;項目使用 MIT 開源許可協議;
最外層使用Viewbox為父控件內部嵌套創建三組
Grid -> Ellipse 、 Border
分別給它們指定不同的Angle從左側開始-135 225 54
,做永久 ?Angle 動畫;如何繪制;

對Ellipse的StrokeDashArray進行設置23 100就能達到效果;
1)RingLoading.cs代碼如下;
using?System.Windows;
using?System.Windows.Controls;namespace?WPFDevelopers.Controls
{public?class?RingLoading?:?Control{//?Using?a?DependencyProperty?as?the?backing?store?for?IsStart.??This?enables?animation,?styling,?binding,?etc...public?static?readonly?DependencyProperty?IsStartProperty?=DependencyProperty.Register("IsStart",?typeof(bool),?typeof(RingLoading),?new?PropertyMetadata(default));//?Using?a?DependencyProperty?as?the?backing?store?for?ProgressValue.??This?enables?animation,?styling,?binding,?etc...public?static?readonly?DependencyProperty?ProgressValueProperty?=DependencyProperty.Register("ProgressValue",?typeof(double),?typeof(RingLoading),new?PropertyMetadata(0d,?OnProgressValueChangedCallBack));//?Using?a?DependencyProperty?as?the?backing?store?for?Progress.??This?enables?animation,?styling,?binding,?etc...internal?static?readonly?DependencyProperty?ProgressProperty?=DependencyProperty.Register("Progress",?typeof(string),?typeof(RingLoading),?new?PropertyMetadata(default));//?Using?a?DependencyProperty?as?the?backing?store?for?Maximum.??This?enables?animation,?styling,?binding,?etc...public?static?readonly?DependencyProperty?MaximumProperty?=DependencyProperty.Register("Maximum",?typeof(double),?typeof(RingLoading),new?PropertyMetadata(100d,?OnMaximumPropertyChangedCallBack));//?Using?a?DependencyProperty?as?the?backing?store?for?Description.??This?enables?animation,?styling,?binding,?etc...public?static?readonly?DependencyProperty?DescriptionProperty?=DependencyProperty.Register("Description",?typeof(string),?typeof(RingLoading),new?PropertyMetadata(default));static?RingLoading(){DefaultStyleKeyProperty.OverrideMetadata(typeof(RingLoading),new?FrameworkPropertyMetadata(typeof(RingLoading)));}public?bool?IsStart{get?=>?(bool)GetValue(IsStartProperty);set?=>?SetValue(IsStartProperty,?value);}public?double?ProgressValue{get?=>?(double)GetValue(ProgressValueProperty);set?=>?SetValue(ProgressValueProperty,?value);}internal?string?Progress{get?=>?(string)GetValue(ProgressProperty);set?=>?SetValue(ProgressProperty,?value);}public?double?Maximum{get?=>?(double)GetValue(MaximumProperty);set?=>?SetValue(MaximumProperty,?value);}public?string?Description{get?=>?(string)GetValue(DescriptionProperty);set?=>?SetValue(DescriptionProperty,?value);}private?static?void?OnProgressValueChangedCallBack(DependencyObject?d,?DependencyPropertyChangedEventArgs?e){if?(!(d?is?RingLoading?control))return;if?(!double.TryParse(e.NewValue?.ToString(),?out?var?value))return;var?progress?=?value?/?control.Maximum;control.SetCurrentValue(ProgressProperty,?progress.ToString("P0"));}private?static?void?OnMaximumPropertyChangedCallBack(DependencyObject?d,?DependencyPropertyChangedEventArgs?e){if?(!(d?is?RingLoading?control))return;if?(!double.TryParse(e.NewValue?.ToString(),?out?var?maxValue))return;if?(maxValue?<=?0)return;var?progress?=?control.ProgressValue?/?maxValue;control.SetCurrentValue(ProgressProperty,?progress.ToString("P0"));}}
}
2)RingLoading.xaml代碼如下;
<Style?TargetType="controls:RingLoading"?BasedOn="{StaticResource?ControlBasicStyle}"><Setter?Property="Template"><Setter.Value><ControlTemplate?TargetType="controls:RingLoading"><ControlTemplate.Resources><Storyboard?x:Key="PART_Resource_Storyboard"?RepeatBehavior="Forever"><DoubleAnimation?To="-495"?Duration="0:0:1.5"?Storyboard.TargetName="PART_Ring1"??Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/><DoubleAnimation?To="585"?Duration="0:0:1.5"?Storyboard.TargetName="PART_Ring2"??Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/><DoubleAnimation?To="-315"?Duration="0:0:1.5"?Storyboard.TargetName="PART_Ring3"??Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/></Storyboard></ControlTemplate.Resources><Grid><Grid.RowDefinitions><RowDefinition?Height="*"/><RowDefinition?Height="Auto"/></Grid.RowDefinitions><Viewbox?HorizontalAlignment="Center"?VerticalAlignment="Center"?><Border?Padding="10"?Width="100"?Height="100"?><Grid><Grid?x:Name="PART_Ring1"?Width="60"?Height="60"?HorizontalAlignment="Center"?VerticalAlignment="Top"?RenderTransformOrigin="0.5,0.5"><Grid.RenderTransform><TransformGroup><ScaleTransform/><SkewTransform/><RotateTransform?Angle="-135"/><TranslateTransform/></TransformGroup></Grid.RenderTransform><Ellipse?Stroke="Red"?StrokeThickness="2"?StrokeDashArray="23?100"?RenderTransformOrigin="0.5,0.5"/><Border?Width="10"?Height="10"?CornerRadius="10"?Background="Red"?HorizontalAlignment="Right"?Margin="0,0,-4,0"><Border.Effect><DropShadowEffect?BlurRadius="10"?ShadowDepth="0"?Color="Red"/></Border.Effect></Border></Grid><Grid?x:Name="PART_Ring2"?Width="60"?Height="60"?HorizontalAlignment="Left"?VerticalAlignment="Bottom"?RenderTransformOrigin="0.5,0.5"><Grid.RenderTransform><TransformGroup><ScaleTransform/><SkewTransform/><RotateTransform?Angle="225"/><TranslateTransform/></TransformGroup></Grid.RenderTransform><Ellipse?Stroke="Purple"?StrokeThickness="2"?StrokeDashArray="23?100"/><Border?Width="10"?Height="10"?CornerRadius="10"?Background="Purple"?VerticalAlignment="Bottom"?HorizontalAlignment="Center"?Margin="0,0,0,-4"><Border.Effect><DropShadowEffect?BlurRadius="10"?ShadowDepth="0"?Color="Purple"/></Border.Effect></Border></Grid><Grid?x:Name="PART_Ring3"?Width="60"?Height="60"?HorizontalAlignment="Right"?VerticalAlignment="Bottom"?RenderTransformOrigin="0.5,0.5"><Grid.RenderTransform><TransformGroup><ScaleTransform/><SkewTransform/><RotateTransform?Angle="45"/><TranslateTransform/></TransformGroup></Grid.RenderTransform><Ellipse?Stroke="#0fb8b2"?StrokeThickness="2"?StrokeDashArray="23?100"/><Border?Width="10"?Height="10"?CornerRadius="10"?Background="#0fb8b2"?HorizontalAlignment="Right"?Margin="0,0,-4,0"><Border.Effect><DropShadowEffect?BlurRadius="10"?ShadowDepth="0"?Color="#0fb8b2"/></Border.Effect></Border></Grid></Grid></Border></Viewbox><StackPanel?Grid.Row="1"?Grid.ColumnSpan="2"?Margin="10"><TextBlock?HorizontalAlignment="Center"?Text="Loading..."?Margin="0,0,0,15"/><TextBlock?HorizontalAlignment="Center"?Text="{TemplateBinding?Description}"?Margin="0,0,0,15"/><TextBlock?HorizontalAlignment="Center"?Text="{TemplateBinding?Progress}"?FontSize="{StaticResource?TitleFontSize}"?FontWeight="Bold"/></StackPanel></Grid><ControlTemplate.Triggers><Trigger?Property="IsStart"?Value="True"><Trigger.EnterActions><BeginStoryboard?Storyboard="{StaticResource?PART_Resource_Storyboard}"?x:Name="PART_BeginStoryboard"/></Trigger.EnterActions><Trigger.ExitActions><StopStoryboard?BeginStoryboardName="PART_BeginStoryboard"/></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>
3)RingLoadingExample.xaml代碼如下;
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.RingLoadingExample"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:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"mc:Ignorable="d"?d:DesignHeight="450"?d:DesignWidth="800"><Grid><wpfdev:RingLoading?IsStart="true"?Width="400"?Height="400"Description="WPFDevelopers"?Foreground="Black"?ProgressValue="50"/></Grid>
</UserControl>
RingLoading|Github[1]
RingLoading|碼云[2]
RingLoading.xaml|Github[3]
RingLoading.xaml|碼云[4]
參考資料
[1]
ThemeControl|Github: https://github.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers/Controls/Loadings/RingLoading.cs
[2]ThemeControl|碼云: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers/Controls/Loadings/RingLoading.cs
[3]Styles.ThemeControl.xaml|Github: https://github.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers/Themes/LoadingGroup.xaml
[4]Styles.ThemeControl.xaml|碼云: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers/Themes/LoadingGroup.xaml