WPF实现在控件上显示Loading等待动画的方法详解
wpF 如何在控件上显示 Loading 等待动画
- 框架使用
.NET40
; Visual Studio 2022
;- 使用方式需引入命名空间后设置控件的附加属性
wd:Loading.IsShow="true"
,即可显示默认等待动画效果如下:
- 如需自定义
Loading
一定要 先设置wd:Loading.Child
在设置IsShow="true&qwww.devze.comuot;
。 - 显示不同
Loading
内容需wd:Loading.Child ={x:Static wd:NormalLoading.Default}
进行复js赋值显示NormalLoading
效果如下:
github[2]
Github xaml[3]
Gitee[4]
Gitee xaml[5]
实现代码
也可以自定义 Loading
动画如下:
1、自定义控件 CustomLoading
。
publicclassCpythonustomLoading:Control { publicstaticCustomLoadingDefault=newCustomLoading(); staticCustomLoading() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomLoading), newFrameworkPropertyMetadata(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}"> <!--此处编写自定义的动画逻辑--> </ControlTemplate> </Setter.Value> </Setter> </Style>
1)创建装饰 AdornerContainer
代码如下:
usingSystem.Windows; usingSystem.Windows.Documents; usingSystem.Windows.Media; namespaceWPFDevelopers.Utilities { publicclassAdornerContainer:Adorner { privateUIElement_child; publicAdornerContainer(UIElementadornedElement):base(adornedElement) { } publicUIElementChild { get=>_child; set { if(value==null) { RemoveVisualChild(_child); _child=value; return; } AddVisualChild(value); _child=value; } } protectedoverrideintVisualChildrenCount { get { return_child!=null?1:0; } } protectedoverrideSizeArrangeOverride(SizefinalSize) { _child?.Arrange(newRect(finalSize)); returnfinalSize; } protectedoverrideVisualGetVisualChild(intindex) { if(index==0&&_child!=null)return_child; returnbase.GetVisualChild(index); } } }
2)创建蒙板控件 MaskControl
代码如下:
usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Media; namespaceWPFDevelopers.Controls { publicclassMaskControl:ContentControl { privatereadonlyVisualvisual; publicstaticreadonlyDependencyPropertyCornerRadiusProperty= DependencyProperty.Register("CornerRadius",typeof(CornerRadius),typeof(MaskControl), newPropertyMetadata(newCornerRadius(0))); publicMaskControl(Visual_visual) { visual=_visual; } publicCornerRadiusCornerRadius { get=>(CornerRadius)GetValue(CornerRadiusProperty); set=>SetValue(CornerRadiusProperty,value); } } }
3)创建 Loading
继承 BaseControl
增加附加属性 IsShow
代码如下:
True
则动态添加装饰器AdornerContainer
并将MaskControl
添加到AdornerContainer.Child
中。False
则移除装饰器。
usingSystem.Runtime.CompilerServices; usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Documents; usingSystem.Windows.Markup; usingSystem.Windows.Media; usingWPFDevelopers.Helpers; usingWPFDevelopers.Utilities; namespaceWPFDevelopers.Controls { publicclassLoading:BaseControl { publicstaticreadonlyDependencyPropertyIsShowProperty= DependencyProperty.RegisterAttached("IsShpythonow",typeof(bool),typeof(Loading), newPropertyMetadata(false,OnIsLoadingChanged)); privateconstshortSIZE=25; privateconstdoubleMINSIZE=40; privatestaticFrameworkElementoldFrameworkElement; privatestaticvoidOnIsLoadingChanged(DependencyObjectd,DependencyPropertyChangedEventArgse) { if(e.NewValueisboolisMask&&disFrameworkElementparent) { if(isMask) { if(!parent.IsLoaded) parent.Loaded+=Parent_Loaded; else CreateMask(parent); } else { parent.Loaded-=Parent_Loaded; CreateMask(parent,true); } } } privatestaticvoidParent_Loaded(objectsender,RoutedEventArgse) { if(senderisUIElementelement) CreateMask(element); } staticvoidCreateMask(UIElementuIElement,boolisRemove=false) { varlayer=AdornerLayer.GetAdornerLayer(uIElement); if(layer==null)return; if(isRemove&&uIElement!=null) { varadorners=layer.GetAdorners(uIElement); if(adorners!=null) { foreach(variteminadorners) { if(itemisAdornerContainercontainer) { varisAddChild=(bool)Loading.GetIsAddChild(uIElement); if(!isAddChild) Loading.SetChild(uIElement,null); container.Child=null; layer.Remove(container); } } } return; } varadornerContainer=newAdornerContainer(uIElement); varvalue=Loading.GetChild(uIElement); if(value==null) { varisLoading=GetIsShow(uIElement); if(isLoading) { varw=(double)uIElement.GetValue(ActualWidthProperty); varh=(double)uIElement.GetValue(ActualHeightProperty); vardefaultLoading=newDefaultLoading(); if(w<MINSIZE||h<MINSIZE) { defaultLoading.Width=SIZE; defaultLoading.Height=SIZE; defaultLoading.StrokeArray=newDoubleCollection{10,100}; } SetChild(uIElement,defaultLoading); value=Loading.GetChild(uIElement); } if(value!=null) adornerContainer.Child=newMaskControl(uIElement){Content=value,Background=ControlsHelper.Brush}; } else { varnormalLoading=(FrameworkElement)value; varframeworkElement=(FrameworkElement)uIElement; Loading.SetIsAddChild(uIElement,true); if(oldFrameworkElement!=null) value=oldFrameworkElement; else { stringxaml=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=newMaskControl(uIElement){Content=value,Background=ControlsHelper.Brush}; } layer.Add(adornerContainer); } publicstaticboolGetIsShow(DependencyObjectobj) { return(bool)obj.GetValue(IsShowProperty); } publicstaticvoidSetIsShow(DependencyObjectobj,boolvalue) { obj.SetValue(IsShowProperty,value); } } }
4)创建 DefaultLoading.xaml
代码如下:
<ResourceDictionaryXMLns="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> <Resour开发者_JS培训ceDictionarySource="Basic/ControlBasic.xaml"/> </ResourceDictionary.MergedDictionaries> <StyleTargetType="{x:Typecontrols:DefaultLoading}"> <SetterProperty="Width"Value="40"/> <SetterProperty="Height"Value="40"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:Typecontrols:DefaultLoading}"> <ViewboxWidth="{TemplateBindingWidth}" Height="{TemplateBindingHeight}"> <controls:SmallPanel> <controls:SmallPanel.Resources> <Storyboardx:Key="StarStoryboard"RepeatBehavior="Forever"> <DoubleAnimation Storyboard.TargetName="PART_Ellipse" Storyboard.TargetProperty="(UIElement.Rendhttp://www.devze.comerTransform).(RotateTransform.Angle)" To="360" Duration="0:0:1.0"/> </Storyboard> </controls:SmallPanel.Resources> <Ellipse Width="{TemplateBindingWidth}" Height="{TemplateBindingHeight}" Stroke="{DynamicResourceBaseSolidColorBrush}" StrokeDashArray="100,100" StrokeThickness="2"/> <Ellipse x:Name="PART_Ellipse" Width="{TemplateBindingWidth}" Height="{TemplateBindingHeight}" Stretch="Uniform" RenderTransformOrigin=".5,.5" Stroke="{DynamicResourcePrimaryPressedSolidColorBrush}" StrokeDashArray="{TemplateBindingStrokeArray}" StrokeThickness="2"> <Ellipse.RenderTransform> <RotateTransformAngle="0"/> </Ellipse.RenderTransform> <Ellipse.Triggers> <EventTriggerRoutedEvent="Loaded"> <BeginStoryboardStoryboard="{StaticResourceStarStoryboard}"/> </EventTrigger> </Ellipse.Triggers> </Ellipse> </controls:SmallPanel> </Viewbox> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
5)创建 LoadingExample.xaml
实例代码如下:
<UserControlx: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"> <GridMargin="10"> <StackPanelGrid.Column="1"> <CheckBoxName="MyCheckBox"Content="启动Loading动画" VerticalAlignment="Center" HorizontalAlignment="Center"/> <UniformGridMargin="10"Rows="2"Columns="3"> <BorderBackground="Red" wd:Loading.IsShow="{BindingElementName=MyCheckBox,Path=IsChecked}"> <TextblockText="Mask0" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Border> <ImageSource="pack://application:,,,/WPFDevelopers.Samples;component/Images/Breathe/0.jpg" wd:Loading.IsShow="{BindingElementName=MyCheckBox,Path=IsChecked}" wd:Loading.Child="{x:Staticwd:NormalLoading.Default}"/> <ButtonContent="Mask1"wd:Loading.IsShow="{BindingElementName=MyCheckBox,Path=IsChecked}"Height="28" VerticalAlignment="Top"HorizontalAlignment="Center"/> <ButtonContent="Mask2"wd:Loading.IsShow="{BindingElementName=MyCheckBox,Path=IsChecked}" VerticalAlignment="Top"HorizontalAlignment="Center"Margin="0,10"/> <ButtonContent="提交"wd:Loading.IsShow="{BindingElementName=MyCheckBox,Path=IsChecked}" VerticalAlignment="Top"HorizontalAlignment="Center"Margin="0,10" Style="{StaticResourcePrimaryButton}"/> </UniformGrid> </StackPanel> </Grid> </UserControl>
效果图
到此这篇关于WPF实现在控件上显示Loading等待动画的方法详解的文章就介绍到这了,更多相关WPF控件显示Loading等待动画内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论