开发者

WPF实现在控件上显示Loading等待动画的方法详解

wpF 如何在控件上显示 Loading 等待动画

  • 框架使用.NET40
  • Visual Studio 2022;
  • 使用方式需引入命名空间后设置控件的附加属性 wd:Loading.IsShow="true",即可显示默认等待动画效果如下:

WPF实现在控件上显示Loading等待动画的方法详解

  • 如需自定义 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]

WPF实现在控件上显示Loading等待动画的方法详解

实现代码

也可以自定义 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等待动画的方法详解的文章就介绍到这了,更多相关WPF控件显示Loading等待动画内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜