开发者

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

开发者 https://www.devze.com 2023-03-24 10:50 出处:网络 作者: 驚鏵
wpF 如何在控件上显示 Loading 等待动画 框架使用.NET40;Visual Studio 2022;使用方式需引入命名空间后设置控件的附加属性 wd:Loading.IsShow="true",即可显示默认等待动画效果如下:

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

精彩评论

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