文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

WPF如何实现在控件上显示Loading等待动画

2023-07-05 16:10

关注

这篇文章主要介绍了WPF如何实现在控件上显示Loading等待动画的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇WPF如何实现在控件上显示Loading等待动画文章都会有所收获,下面我们一起来看看吧。

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

WPF如何实现在控件上显示Loading等待动画

Github[2]

Github xaml[3]

Gitee[4]

Gitee xaml[5]

WPF如何实现在控件上显示Loading等待动画

实现代码

也可以自定义 Loading 动画如下:

自定义控件 CustomLoading 。

public class CustomLoading : Control    {        public static CustomLoading Default = new CustomLoading();        static CustomLoading()        {            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomLoading),                new FrameworkPropertyMetadata(typeof(CustomLoading)));        }    }

编写 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 代码如下:

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)创建蒙板控件 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)创建 Loading 继承 BaseControl 增加附加属性 IsShow 代码如下:

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)创建 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)创建 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>

效果图

WPF如何实现在控件上显示Loading等待动画

关于“WPF如何实现在控件上显示Loading等待动画”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“WPF如何实现在控件上显示Loading等待动画”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯