老板加薪!看我做的 WPF Loading!

2022-08-10 11:21:07 +08:00
 yanjinhua

老板加薪!看我做的 WPF Loading !!!

控件名:RingLoading

作者:WPFDevelopersOrg

原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal

👉视频点我效果预览⬅⬅

1 )RingLoading.cs代码如下;

using System.Windows;
using System.Windows.Controls;

namespace WPFDevelopers.Controls
{
    public class RingLoading : Control
    {
        // Using a DependencyProperty as the backing store for IsStart.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsStartProperty =
            DependencyProperty.Register("IsStart", typeof(bool), typeof(RingLoading), new PropertyMetadata(default));

        // Using a DependencyProperty as the backing store for ProgressValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ProgressValueProperty =
            DependencyProperty.Register("ProgressValue", typeof(double), typeof(RingLoading),
                new PropertyMetadata(0d, OnProgressValueChangedCallBack));

        // Using a DependencyProperty as the backing store for Progress.  This enables animation, styling, binding, etc...
        internal static readonly DependencyProperty ProgressProperty =
            DependencyProperty.Register("Progress", typeof(string), typeof(RingLoading), new PropertyMetadata(default));

        // Using a DependencyProperty as the backing store for Maximum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(RingLoading),
                new PropertyMetadata(100d, OnMaximumPropertyChangedCallBack));

        // Using a DependencyProperty as the backing store for Description.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DescriptionProperty =
            DependencyProperty.Register("Description", typeof(string), typeof(RingLoading),
                new PropertyMetadata(default));

        static RingLoading()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RingLoading),
                new FrameworkPropertyMetadata(typeof(RingLoading)));
        }

        public bool IsStart
        {
            get => (bool)GetValue(IsStartProperty);
            set => SetValue(IsStartProperty, value);
        }


        public double ProgressValue
        {
            get => (double)GetValue(ProgressValueProperty);
            set => SetValue(ProgressValueProperty, value);
        }


        internal string Progress
        {
            get => (string)GetValue(ProgressProperty);
            set => SetValue(ProgressProperty, value);
        }


        public double Maximum
        {
            get => (double)GetValue(MaximumProperty);
            set => SetValue(MaximumProperty, value);
        }

        public string Description
        {
            get => (string)GetValue(DescriptionProperty);
            set => SetValue(DescriptionProperty, value);
        }

        private static void OnProgressValueChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is RingLoading control))
                return;

            if (!double.TryParse(e.NewValue?.ToString(), out var value))
                return;

            var progress = value / control.Maximum;
            control.SetCurrentValue(ProgressProperty, progress.ToString("P0"));
        }

        private static void OnMaximumPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is RingLoading control))
                return;

            if (!double.TryParse(e.NewValue?.ToString(), out var maxValue))
                return;

            if (maxValue <= 0)
                return;

            var progress = control.ProgressValue / maxValue;
            control.SetCurrentValue(ProgressProperty, progress.ToString("P0"));
        }
    }
}

2 )RingLoading.xaml代码如下;

 <Style TargetType="controls:RingLoading" BasedOn="{StaticResource ControlBasicStyle}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="controls:RingLoading">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="PART_Resource_Storyboard" RepeatBehavior="Forever">
                            <DoubleAnimation To="-495" Duration="0:0:1.5" Storyboard.TargetName="PART_Ring1"  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/>
                            <DoubleAnimation To="585" Duration="0:0:1.5" Storyboard.TargetName="PART_Ring2"  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/>
                            <DoubleAnimation To="-315" Duration="0:0:1.5" Storyboard.TargetName="PART_Ring3"  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"/>
                        </Storyboard>
                    </ControlTemplate.Resources>

                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>

                        <Viewbox HorizontalAlignment="Center" VerticalAlignment="Center" >
                            <Border Padding="10" Width="100" Height="100" >
                                <Grid>
                                    <Grid x:Name="PART_Ring1" Width="60" Height="60" HorizontalAlignment="Center" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5">
                                        <Grid.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="-135"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Grid.RenderTransform>
                                        <Ellipse Stroke="Red" StrokeThickness="2" StrokeDashArray="23 100" RenderTransformOrigin="0.5,0.5"/>
                                        <Border Width="10" Height="10" CornerRadius="10" Background="Red" HorizontalAlignment="Right" Margin="0,0,-4,0">
                                            <Border.Effect>
                                                <DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="Red"/>
                                            </Border.Effect>
                                        </Border>
                                    </Grid>

                                    <Grid x:Name="PART_Ring2" Width="60" Height="60" HorizontalAlignment="Left" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5">
                                        <Grid.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="225"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Grid.RenderTransform>
                                        <Ellipse Stroke="Purple" StrokeThickness="2" StrokeDashArray="23 100"/>
                                        <Border Width="10" Height="10" CornerRadius="10" Background="Purple" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,-4">
                                            <Border.Effect>
                                                <DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="Purple"/>
                                            </Border.Effect>
                                        </Border>
                                    </Grid>

                                    <Grid x:Name="PART_Ring3" Width="60" Height="60" HorizontalAlignment="Right" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5">
                                        <Grid.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="45"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Grid.RenderTransform>
                                        <Ellipse Stroke="#0fb8b2" StrokeThickness="2" StrokeDashArray="23 100"/>
                                        <Border Width="10" Height="10" CornerRadius="10" Background="#0fb8b2" HorizontalAlignment="Right" Margin="0,0,-4,0">
                                            <Border.Effect>
                                                <DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="#0fb8b2"/>
                                            </Border.Effect>
                                        </Border>
                                    </Grid>
                                </Grid>
                            </Border>
                        </Viewbox>

                        <StackPanel Grid.Row="1" Grid.ColumnSpan="2" Margin="10">
                            <TextBlock HorizontalAlignment="Center" Text="Loading..." Margin="0,0,0,15"/>
                            <TextBlock HorizontalAlignment="Center" Text="{TemplateBinding Description}" Margin="0,0,0,15"/>
                            <TextBlock HorizontalAlignment="Center" Text="{TemplateBinding Progress}" FontSize="{StaticResource TitleFontSize}" 
                                       FontWeight="Bold"/>
                        </StackPanel>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsStart" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource PART_Resource_Storyboard}" x:Name="PART_BeginStoryboard"/>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <StopStoryboard BeginStoryboardName="PART_BeginStoryboard"/>
                            </Trigger.ExitActions>
                        </Trigger>

                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

3 )RingLoadingExample.xaml代码如下;

<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.RingLoadingExample"
             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:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"
             xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <wpfdev:RingLoading IsStart="true" 
                            Width="400" Height="400"
                            Description="WPFDevelopers" Foreground="Black" ProgressValue="50"/>
    </Grid>
</UserControl>

RingLoading|Github
RingLoading|码云
RingLoading.xaml|Github
RingLoading.xaml|码云

5146 次点击
所在节点    .NET
34 条回复
Terry05
2022-08-10 11:26:22 +08:00
emmmmmm……恕我没看懂
y830CAa5nink4rUQ
2022-08-10 11:28:36 +08:00
老板:这么丑?撤掉,换回上一版那个 GIF !
runningowl
2022-08-10 12:34:52 +08:00
Lottie 不香么
loopinfor
2022-08-10 12:40:02 +08:00
这个 loading 效果过于另类了,应该不会有人真的用吧
yanjinhua
2022-08-10 13:15:26 +08:00
yanjinhua
2022-08-10 13:15:40 +08:00
@loopinfor 哈哈哈
yanjinhua
2022-08-10 13:16:05 +08:00
@DrX 没用 gif
yanjinhua
2022-08-10 13:16:44 +08:00
@Terry05 呃呃呃呃呃
wangyzj
2022-08-10 14:05:29 +08:00
不够卷
SeanTheSheep
2022-08-10 14:05:48 +08:00
逛 V 站一年了,第二次看到 WPF 相关的帖子,泪目了。
yanjinhua
2022-08-10 15:31:29 +08:00
@wangyzj 正在努力
yanjinhua
2022-08-10 15:31:55 +08:00
@SeanTheSheep 那么我很关心第一次的帖子 i😊
20015jjw
2022-08-10 15:42:37 +08:00
amazon 可能会喜欢你(雾
sinnosong1
2022-08-10 16:06:39 +08:00
每行都能看懂,但是连起来就完全看不懂了,虽然我也写过 WPF ,一直都是入门状态的新手。。。
yanjinhua
2022-08-10 16:12:15 +08:00
@sinnosong1 哈哈哈,好像懂了 但是又没完全懂
yanjinhua
2022-08-10 16:12:32 +08:00
@20015jjw 我不懂了
vone
2022-08-10 16:24:57 +08:00
当场开除!
dcsuibian
2022-08-10 16:43:54 +08:00
现在 Electron 越来越多,对原生开发者也越来越敬重
villivateur
2022-08-10 16:47:06 +08:00
star 了,准备在我丑得要命的上位机里面试下这个主题
stoluoyu
2022-08-10 16:49:15 +08:00
精子有了,load 完不该进入卵子了么(大雾

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/871883

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX