WPF實(shí)現(xiàn)在控件上顯示Loading等待動(dòng)畫的方法詳解
WPF 如何在控件上顯示 Loading 等待動(dòng)畫
- 框架使用
.NET40; Visual Studio 2022;- 使用方式需引入命名空間后設(shè)置控件的附加屬性
wd:Loading.IsShow="true",即可顯示默認(rèn)等待動(dòng)畫效果如下:

- 如需自定義
Loading一定要 先設(shè)置wd:Loading.Child在設(shè)置IsShow="true"。 - 顯示不同
Loading內(nèi)容需wd:Loading.Child ={x:Static wd:NormalLoading.Default}進(jìn)行復(fù)賦值顯示NormalLoading效果如下:

實(shí)現(xiàn)代碼
也可以自定義 Loading 動(dòng)畫如下:
1、自定義控件 CustomLoading 。
public?class?CustomLoading?:?Control
????{
????????public?static?CustomLoading?Default?=?new?CustomLoading();
????????static?CustomLoading()
????????{
????????????DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomLoading),
????????????????new?FrameworkPropertyMetadata(typeof(CustomLoading)));
????????}
????}
2、編寫 CustomLoading.xaml 代碼如下。
<Style TargetType="{x:Type controls:CustomLoading}">
<Setter Property="Width" Value="40" />
<Setter Property="Height" Value="40" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:CustomLoading}">
<!--此處編寫自定義的動(dòng)畫邏輯-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
1)創(chuàng)建裝飾 AdornerContainer 代碼如下:
using?System.Windows;
using?System.Windows.Documents;
using?System.Windows.Media;
namespace?WPFDevelopers.Utilities
{
????public?class?AdornerContainer?:?Adorner
????{
????????private?UIElement?_child;
????????public?AdornerContainer(UIElement?adornedElement)?:?base(adornedElement)
????????{
????????}
????????public?UIElement?Child
????????{
????????????get?=>?_child;
????????????set
????????????{
????????????????if?(value?==?null)
????????????????{
????????????????????RemoveVisualChild(_child);
????????????????????_child?=?value;
????????????????????return;
????????????????}
????????????????AddVisualChild(value);
????????????????_child?=?value;
????????????}
????????}
????????protected?override?int?VisualChildrenCount
????????{
????????????get
????????????{
????????????????return?_child?!=?null???1?:?0;
????????????}
????????}
????????protected?override?Size?ArrangeOverride(Size?finalSize)
????????{
????????????_child?.Arrange(new?Rect(finalSize));
????????????return?finalSize;
????????}
????????protected?override?Visual?GetVisualChild(int?index)
????????{
????????????if?(index?==?0?&&?_child?!=?null)?return?_child;
????????????return?base.GetVisualChild(index);
????????}
????}
}2)創(chuàng)建蒙板控件 MaskControl 代碼如下:
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Media;
namespace?WPFDevelopers.Controls
{
????public?class?MaskControl?:?ContentControl
????{
????????private?readonly?Visual?visual;
????????public?static?readonly?DependencyProperty?CornerRadiusProperty?=
??????????DependencyProperty.Register("CornerRadius",?typeof(CornerRadius),?typeof(MaskControl),?
??????????????new?PropertyMetadata(new?CornerRadius(0)));
????????public?MaskControl(Visual?_visual)
????????{
????????????visual?=?_visual;
????????}
????????public?CornerRadius?CornerRadius
????????{
????????????get?=>?(CornerRadius)GetValue(CornerRadiusProperty);
????????????set?=>?SetValue(CornerRadiusProperty,?value);
????????}
????}
}
3)創(chuàng)建 Loading 繼承 BaseControl 增加附加屬性 IsShow 代碼如下:
True則動(dòng)態(tài)添加裝飾器AdornerContainer并將MaskControl添加到AdornerContainer.Child中。False則移除裝飾器。
using?System.Runtime.CompilerServices;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Documents;
using?System.Windows.Markup;
using?System.Windows.Media;
using?WPFDevelopers.Helpers;
using?WPFDevelopers.Utilities;
namespace?WPFDevelopers.Controls
{
????public?class?Loading?:?BaseControl
????{
????????public?static?readonly?DependencyProperty?IsShowProperty?=
???????????DependencyProperty.RegisterAttached("IsShow",?typeof(bool),?typeof(Loading),
???????????????new?PropertyMetadata(false,?OnIsLoadingChanged));
????????private?const?short?SIZE?=?25;
????????private?const?double?MINSIZE?=?40;
????????private?static?FrameworkElement?oldFrameworkElement;
????????private?static?void?OnIsLoadingChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)
????????{
????????????if?(e.NewValue?is?bool?isMask?&&?d?is?FrameworkElement?parent)
????????????{
????????????????if?(isMask)
????????????????{
????????????????????if?(!parent.IsLoaded)
????????????????????????parent.Loaded?+=?Parent_Loaded;
????????????????????else
????????????????????????CreateMask(parent);
????????????????}
????????????????else
????????????????{
????????????????????parent.Loaded?-=?Parent_Loaded;
????????????????????CreateMask(parent,?true);
????????????????}
????????????}
????????}
????????private?static?void?Parent_Loaded(object?sender,?RoutedEventArgs?e)
????????{
????????????if?(sender?is?UIElement?element)
????????????????CreateMask(element);
????????}
????????static?void?CreateMask(UIElement?uIElement,?bool?isRemove?=?false)
????????{
????????????var?layer?=?AdornerLayer.GetAdornerLayer(uIElement);
????????????if?(layer?==?null)?return;
????????????if?(isRemove?&&?uIElement?!=?null)
????????????{
????????????????var?adorners?=?layer.GetAdorners(uIElement);
????????????????if?(adorners?!=?null)
????????????????{
????????????????????foreach?(var?item?in?adorners)
????????????????????{
????????????????????????if?(item?is?AdornerContainer?container)
????????????????????????{
????????????????????????????var?isAddChild?=?(bool)Loading.GetIsAddChild(uIElement);
????????????????????????????if?(!isAddChild)
????????????????????????????????Loading.SetChild(uIElement,?null);
????????????????????????????container.Child?=?null;
????????????????????????????layer.Remove(container);
????????????????????????}
????????????????????}
????????????????}
????????????????return;
????????????}
????????????var?adornerContainer?=?new?AdornerContainer(uIElement);
????????????var?value?=?Loading.GetChild(uIElement);
????????????if?(value?==?null)
????????????{
????????????????var?isLoading?=?GetIsShow(uIElement);
????????????????if?(isLoading)
????????????????{
????????????????????var?w?=?(double)uIElement.GetValue(ActualWidthProperty);
????????????????????var?h?=?(double)uIElement.GetValue(ActualHeightProperty);
????????????????????var?defaultLoading?=?new?DefaultLoading();
????????????????????if?(w?<?MINSIZE?||?h?<?MINSIZE)
????????????????????{
????????????????????????defaultLoading.Width?=?SIZE;
????????????????????????defaultLoading.Height?=?SIZE;
????????????????????????defaultLoading.StrokeArray?=?new?DoubleCollection?{?10,?100?};
????????????????????}
????????????????????SetChild(uIElement,?defaultLoading);
????????????????????value?=?Loading.GetChild(uIElement);
????????????????}
????????????????if?(value?!=?null)
????????????????????adornerContainer.Child?=?new?MaskControl(uIElement)?{?Content?=?value,?Background?=?ControlsHelper.Brush?};
????????????}
????????????else
????????????{
????????????????var?normalLoading?=?(FrameworkElement)value;
????????????????var?frameworkElement?=?(FrameworkElement)uIElement;
????????????????Loading.SetIsAddChild(uIElement,?true);
????????????????if?(oldFrameworkElement?!=?null)
????????????????????value?=?oldFrameworkElement;
????????????????else
????????????????{
????????????????????string?xaml?=?XamlWriter.Save(normalLoading);
????????????????????oldFrameworkElement?=?(FrameworkElement)?XamlReader.Parse(xaml);
????????????????}
????????????????var?_size?=?frameworkElement.ActualHeight?<?frameworkElement.ActualWidth???frameworkElement.ActualHeight?:?frameworkElement.ActualWidth;
????????????????if(_size?<?MINSIZE)
????????????????{
????????????????????normalLoading.Width?=?SIZE;
????????????????????normalLoading.Height?=?SIZE;
????????????????????value?=?normalLoading;
????????????????}
????????????????
????????????????adornerContainer.Child?=?new?MaskControl(uIElement)?{?Content?=?value,?Background?=?ControlsHelper.Brush?};
????????????}
????????????layer.Add(adornerContainer);
????????}
????????public?static?bool?GetIsShow(DependencyObject?obj)
????????{
????????????return?(bool)obj.GetValue(IsShowProperty);
????????}
????????public?static?void?SetIsShow(DependencyObject?obj,?bool?value)
????????{
????????????obj.SetValue(IsShowProperty,?value);
????????}
????}
}
4)創(chuàng)建 DefaultLoading.xaml 代碼如下:
<ResourceDictionary?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????????????????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????????????????????xmlns:controls="clr-namespace:WPFDevelopers.Controls">
????<ResourceDictionary.MergedDictionaries>
????????<ResourceDictionary?Source="Basic/ControlBasic.xaml"/>
????</ResourceDictionary.MergedDictionaries>
????<Style?TargetType="{x:Type?controls:DefaultLoading}">
????????<Setter?Property="Width"?Value="40"?/>
????????<Setter?Property="Height"?Value="40"?/>
????????<Setter?Property="Template">
????????????<Setter.Value>
????????????????<ControlTemplate?TargetType="{x:Type?controls:DefaultLoading}">
????????????????????<Viewbox?Width="{TemplateBinding?Width}"?
?????????????????????????????Height="{TemplateBinding?Height}">
????????????????????????<controls:SmallPanel>
????????????????????????????<controls:SmallPanel.Resources>
????????????????????????????????<Storyboard?x:Key="StarStoryboard"?RepeatBehavior="Forever">
????????????????????????????????????<DoubleAnimation
????????????????????????????????????????????????Storyboard.TargetName="PART_Ellipse"
????????????????????????????????????????????????Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
????????????????????????????????????????????????To="360"
????????????????????????????????????????????????Duration="0:0:1.0"?/>
????????????????????????????????</Storyboard>
????????????????????????????</controls:SmallPanel.Resources>
????????????????????????????<Ellipse
????????????????????????????????????????Width="{TemplateBinding?Width}"
????????????????????????????????????????Height="{TemplateBinding?Height}"
????????????????????????????????????????Stroke="{DynamicResource?BaseSolidColorBrush}"
????????????????????????????????????????StrokeDashArray="100,100"
????????????????????????????????????????StrokeThickness="2"?/>
????????????????????????????<Ellipse
????????????????????????????????????????x:Name="PART_Ellipse"
????????????????????????????????????????Width="{TemplateBinding?Width}"
????????????????????????????????????????Height="{TemplateBinding?Height}"
????????????????????????????????????????Stretch="Uniform"
????????????????????????????????????????RenderTransformOrigin=".5,.5"
????????????????????????????????????????Stroke="{DynamicResource?PrimaryPressedSolidColorBrush}"
????????????????????????????????????????StrokeDashArray="{TemplateBinding?StrokeArray}"
????????????????????????????????????????StrokeThickness="2">
????????????????????????????????<Ellipse.RenderTransform>
????????????????????????????????????<RotateTransform?Angle="0"?/>
????????????????????????????????</Ellipse.RenderTransform>
????????????????????????????????<Ellipse.Triggers>
????????????????????????????????????<EventTrigger?RoutedEvent="Loaded">
????????????????????????????????????????<BeginStoryboard?Storyboard="{StaticResource?StarStoryboard}"?/>
????????????????????????????????????</EventTrigger>
????????????????????????????????</Ellipse.Triggers>
????????????????????????????</Ellipse>
????????????????????????</controls:SmallPanel>
????????????????????</Viewbox>
????????????????</ControlTemplate>
????????????</Setter.Value>
????????</Setter>
????</Style>
</ResourceDictionary>
5)創(chuàng)建 LoadingExample.xaml 實(shí)例代碼如下:
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.LoadingExample"
?????????????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:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
?????????????xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
?????????????mc:Ignorable="d"?
?????????????d:DesignHeight="450"?d:DesignWidth="800">
????????<Grid?Margin="10">
????????????<StackPanel?Grid.Column="1">
????????????????<CheckBox?Name="MyCheckBox"?Content="啟動(dòng)?Loading?動(dòng)畫"
??????????????????????????VerticalAlignment="Center"
??????????????????????????HorizontalAlignment="Center"/>
????????????????<UniformGrid?Margin="10"?Rows="2"?Columns="3">
????????????????????<Border?Background="Red"?
????????????????wd:Loading.IsShow="{Binding?ElementName=MyCheckBox,Path=IsChecked}">
????????????????????????<TextBlock?Text="Mask?0"
???????????????????????VerticalAlignment="Center"?
???????????????????????HorizontalAlignment="Center"/>
????????????????????</Border>
????????????????????<Image?Source="pack://application:,,,/WPFDevelopers.Samples;component/Images/Breathe/0.jpg"
???????????????????wd:Loading.IsShow="{Binding?ElementName=MyCheckBox,Path=IsChecked}"
???????????????????????????wd:Loading.Child="{x:Static?wd:NormalLoading.Default}"/>
????????????????????<Button?Content="Mask?1"?wd:Loading.IsShow="{Binding?ElementName=MyCheckBox,Path=IsChecked}"?Height="28"
????????????????????VerticalAlignment="Top"?HorizontalAlignment="Center"/>
????????????????????<Button?Content="Mask?2"?wd:Loading.IsShow="{Binding?ElementName=MyCheckBox,Path=IsChecked}"
????????????????????VerticalAlignment="Top"?HorizontalAlignment="Center"?Margin="0,10"/>
????????????????????<Button?Content="提交"?wd:Loading.IsShow="{Binding?ElementName=MyCheckBox,Path=IsChecked}"?
????????????????????VerticalAlignment="Top"?HorizontalAlignment="Center"?Margin="0,10"
????????????????????Style="{StaticResource?PrimaryButton}"/>
????????????????</UniformGrid>
????????????</StackPanel>
????????</Grid>
</UserControl>
效果圖

到此這篇關(guān)于WPF實(shí)現(xiàn)在控件上顯示Loading等待動(dòng)畫的方法詳解的文章就介紹到這了,更多相關(guān)WPF控件顯示Loading等待動(dòng)畫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)windows系統(tǒng)重啟和關(guān)機(jī)的代碼詳解
這篇文章主要介紹了C#實(shí)現(xiàn)windows系統(tǒng)重啟和關(guān)機(jī)的的方法,涉及C#調(diào)用windows系統(tǒng)命令實(shí)現(xiàn)控制開機(jī)、關(guān)機(jī)等操作的技巧,非常簡單實(shí)用,需要的朋友可以參考下2024-02-02
C# 導(dǎo)出Excel的6種簡單方法實(shí)現(xiàn)
C# 導(dǎo)出 Excel 的6種簡單方法:數(shù)據(jù)表導(dǎo)出到 Excel,對(duì)象集合導(dǎo)出到 Excel,數(shù)據(jù)庫導(dǎo)出到 Excel,微軟網(wǎng)格控件導(dǎo)出到 Excel,數(shù)組導(dǎo)出到 Excel,CSV 導(dǎo)出到 Excel,你都會(huì)了嗎?需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
詳解WPF如何在Panel中實(shí)現(xiàn)設(shè)置所有子項(xiàng)間距
這篇文章主要為大家詳細(xì)介紹了WPF如何在Panel中實(shí)現(xiàn)設(shè)置所有子項(xiàng)間距,本文借鑒了 Qt 中的 Spacing 設(shè)置方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10

