WPF實現(xiàn)在控件上顯示Loading等待動畫的方法詳解
WPF 如何在控件上顯示 Loading 等待動畫
- 框架使用
.NET40
; Visual Studio 2022
;- 使用方式需引入命名空間后設(shè)置控件的附加屬性
wd:Loading.IsShow="true"
,即可顯示默認等待動畫效果如下:
- 如需自定義
Loading
一定要 先設(shè)置wd:Loading.Child
在設(shè)置IsShow="true"
。 - 顯示不同
Loading
內(nèi)容需wd:Loading.Child ={x:Static wd:NormalLoading.Default}
進行復(fù)賦值顯示NormalLoading
效果如下:
實現(xiàn)代碼
也可以自定義 Loading
動畫如下:
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}"> <!--此處編寫自定義的動畫邏輯--> </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
則動態(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
實例代碼如下:
<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="啟動?Loading?動畫" ??????????????????????????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實現(xiàn)在控件上顯示Loading等待動畫的方法詳解的文章就介紹到這了,更多相關(guān)WPF控件顯示Loading等待動畫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# WinForm窗體編程中處理數(shù)字的正確操作方法
這篇文章主要介紹了C# WinForm窗體編程中處理數(shù)字的正確操作方法,本文給出了正確示例,并解釋了為什么要這么做,需要的朋友可以參考下2014-08-08WCF基礎(chǔ)介紹并創(chuàng)建簡單應(yīng)用程序
這篇文章介紹了WCF基礎(chǔ)并創(chuàng)建簡單WCF應(yīng)用程序,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01C#調(diào)用WinRar執(zhí)行rar、zip壓縮的方法
這篇文章主要介紹了C#調(diào)用WinRar執(zhí)行rar、zip壓縮的方法,涉及C#針對winrar的判斷與調(diào)用技巧,需要的朋友可以參考下2015-05-05C#數(shù)據(jù)類型實現(xiàn)背包、隊列和棧
本文詳細講解了C#數(shù)據(jù)結(jié)構(gòu)類型,并實現(xiàn)背包、隊列和棧的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04