WPF加载微调器

| 目的是显示应用程序正在运行的信息。因此,我正在寻找使用WPF / MVVM的装载微调程序的智能实现示例。     
已邀请:
        我写了这个用户控件,它可能会有所帮助,它将显示带有进度条旋转的消息,以表明它当前正在加载内容。
  <ctr:LoadingPanel x:Name=\"loadingPanel\"
                    IsLoading=\"{Binding PanelLoading}\"
                    Message=\"{Binding PanelMainMessage}\"
                    SubMessage=\"{Binding PanelSubMessage}\" 
                    ClosePanelCommand=\"{Binding PanelCloseCommand}\" />
它具有几个可以绑定的基本属性。     
        为了得到这个: 将此粘贴在用户控件中:
<UserControl.Resources>
    <Color x:Key=\"FilledColor\" A=\"255\" B=\"155\" R=\"155\" G=\"155\"/>
    <Color x:Key=\"UnfilledColor\" A=\"0\" B=\"155\" R=\"155\" G=\"155\"/>

    <Style x:Key=\"BusyAnimationStyle\" TargetType=\"Control\">
        <Setter Property=\"Background\" Value=\"#7F000000\"/>

        <Setter Property=\"Template\">
            <Setter.Value>
                <ControlTemplate TargetType=\"Control\">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key=\"Animation0\" BeginTime=\"00:00:00.0\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse0\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation1\" BeginTime=\"00:00:00.2\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse1\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation2\" BeginTime=\"00:00:00.4\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse2\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation3\" BeginTime=\"00:00:00.6\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse3\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation4\" BeginTime=\"00:00:00.8\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse4\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation5\" BeginTime=\"00:00:01.0\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse5\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation6\" BeginTime=\"00:00:01.2\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse6\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation7\" BeginTime=\"00:00:01.4\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse7\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>
                    </ControlTemplate.Resources>

                    <ControlTemplate.Triggers>
                        <Trigger Property=\"IsVisible\" Value=\"True\">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation0}\" x:Name=\"Storyboard0\" />
                                <BeginStoryboard Storyboard=\"{StaticResource Animation1}\" x:Name=\"Storyboard1\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation2}\" x:Name=\"Storyboard2\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation3}\" x:Name=\"Storyboard3\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation4}\" x:Name=\"Storyboard4\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation5}\" x:Name=\"Storyboard5\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation6}\" x:Name=\"Storyboard6\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation7}\" x:Name=\"Storyboard7\"/>
                            </Trigger.EnterActions>

                            <Trigger.ExitActions>
                                <StopStoryboard BeginStoryboardName=\"Storyboard0\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard1\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard2\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard3\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard4\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard5\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard6\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard7\"/>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>

                    <Border BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Background=\"{TemplateBinding Background}\">
                        <Grid>
                        <Canvas Height=\"60\" Width=\"60\">
                            <Canvas.Resources>
                                <Style TargetType=\"Ellipse\">
                                    <Setter Property=\"Width\" Value=\"15\"/>
                                    <Setter Property=\"Height\" Value=\"15\" />
                                    <Setter Property=\"Fill\" Value=\"#009B9B9B\" />
                                </Style>
                            </Canvas.Resources>

                            <Ellipse x:Name=\"ellipse0\" Canvas.Left=\"1.75\" Canvas.Top=\"21\"/>
                            <Ellipse x:Name=\"ellipse1\" Canvas.Top=\"7\" Canvas.Left=\"6.5\"/>
                            <Ellipse x:Name=\"ellipse2\" Canvas.Left=\"20.5\" Canvas.Top=\"0.75\"/>
                            <Ellipse x:Name=\"ellipse3\" Canvas.Left=\"34.75\" Canvas.Top=\"6.75\"/>
                            <Ellipse x:Name=\"ellipse4\" Canvas.Left=\"40.5\" Canvas.Top=\"20.75\" />
                            <Ellipse x:Name=\"ellipse5\" Canvas.Left=\"34.75\" Canvas.Top=\"34.5\"/>
                            <Ellipse x:Name=\"ellipse6\" Canvas.Left=\"20.75\" Canvas.Top=\"39.75\"/>
                            <Ellipse x:Name=\"ellipse7\" Canvas.Top=\"34.25\" Canvas.Left=\"7\" />
                            <Ellipse Width=\"39.5\" Height=\"39.5\" Canvas.Left=\"8.75\" Canvas.Top=\"8\" Visibility=\"Hidden\"/>
                        </Canvas>
                            <Label Content=\"{Binding Path=Text}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"/>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<Control Style=\"{StaticResource BusyAnimationStyle}\"/>
为了使每个椭圆上的阴影消失,在每个
ColorAnimationUsingKeyFrames
元素之后添加以下内容。确保将其指向正确的椭圆。
<ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse0\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
    <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
    <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse0\" Storyboard.TargetProperty=\"Width\" >
    <DoubleAnimationUsingKeyFrames.KeyFrames>
        <SplineDoubleKeyFrame  KeyTime=\"00:00:00.0\" Value=\"15\" />
        <SplineDoubleKeyFrame  KeyTime=\"00:00:01.0\" Value=\"12\" />
        <SplineDoubleKeyFrame  KeyTime=\"00:00:01.6\" Value=\"0\" />
    </DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=\"ellipse0\" Storyboard.TargetProperty=\"Height\" >
    <DoubleAnimationUsingKeyFrames.KeyFrames>
        <SplineDoubleKeyFrame  KeyTime=\"00:00:00.0\" Value=\"15\" />
        <SplineDoubleKeyFrame  KeyTime=\"00:00:01.0\" Value=\"12\" />
        <SplineDoubleKeyFrame  KeyTime=\"00:00:01.6\" Value=\"0\" />
    </DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>
    
        一个非常简单的“即插即用”微调器可以是Font Awesome Wpf软件包中的旋转图标之一(旋转图标)。 用法很简单,只需安装nuget软件包:
PM> Install-Package FontAwesome.WPF
然后将引用添加到名称空间
xmlns:fa=\"http://schemas.fontawesome.io/icons/\"
并使用ImageAwesome控件。设置Spin = \“ True \”属性,然后选择\“ Spinner \”,\“ Refresh \”,\“ Cog \”和\“ CircleOutlinedNotched \”图标之一。它具有可伸缩性,可以通过设置宽度和高度来调整大小。
<Window x:Class=\"Example.FontAwesome.WPF.Single\"
    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"
    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"
    xmlns:fa=\"http://schemas.fontawesome.io/icons/\"
    Title=\"Single\" Height=\"300\" Width=\"300\">
    <Grid  Margin=\"20\">
        <fa:ImageAwesome Icon=\"Refresh\" Spin=\"True\" Height=\"48\" Width=\"48\" />
    </Grid>
</Window>
    
        有图片 旋转图标选项的视觉摘要。使用Screen To Gif录制。 字体超赞WPF GitHub上的文档。 通过NuGet安装:   PM>安装包FontAwesome.WPF 看起来像这样: XAML:
<fa:ImageAwesome Icon=\"Spinner\" Spin=\"True\" SpinDuration=\"4\" />
图中的图标为
Spinner
CircleOutlineNotch
Refresh
Cog
。还有很多。 @HAdes中的方法 XAML复制/粘贴。     
        在扩展的WPF工具包中签出BusyIndi​​cator。     
        在WPF中,您现在可以简单地执行以下操作:
Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait; // set the cursor to loading spinner

Mouse.OverrideCursor = System.Windows.Input.Cursors.Arrow; // set the cursor back to arrow
    
        这是对@HAdes给出的用于参数化宽度,高度和椭圆尺寸的代码的更新。 此实现可自动计算飞行中所需的角度,宽度和高度。 用户控件绑定到自身(在代码后面),它负责所有计算。 XAML
<UserControl x:Class=\"WpfApplication2.Spinner\"
         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:local=\"clr-namespace:WpfApplication2\"
         mc:Ignorable=\"d\" 
         DataContext=\"{Binding RelativeSource={RelativeSource Self}}\"
         d:DesignHeight=\"300\" d:DesignWidth=\"300\">
<UserControl.Resources>
    <Color x:Key=\"FilledColor\" A=\"255\" B=\"155\" R=\"155\" G=\"155\"/>
    <Color x:Key=\"UnfilledColor\" A=\"0\" B=\"155\" R=\"155\" G=\"155\"/>

    <Style x:Key=\"BusyAnimationStyle\" TargetType=\"Control\">
        <Setter Property=\"Background\" Value=\"Transparent\"/>

        <Setter Property=\"Template\">
            <Setter.Value>
                <ControlTemplate TargetType=\"Control\">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key=\"Animation0\" BeginTime=\"00:00:00.0\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseN\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation1\" BeginTime=\"00:00:00.2\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseNE\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation2\" BeginTime=\"00:00:00.4\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseE\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation3\" BeginTime=\"00:00:00.6\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseSE\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation4\" BeginTime=\"00:00:00.8\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseS\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation5\" BeginTime=\"00:00:01.0\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseSW\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation6\" BeginTime=\"00:00:01.2\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseW\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>

                        <Storyboard x:Key=\"Animation7\" BeginTime=\"00:00:01.4\" RepeatBehavior=\"Forever\">
                            <ColorAnimationUsingKeyFrames Storyboard.TargetName=\"ellipseNW\" Storyboard.TargetProperty=\"(Shape.Fill).(SolidColorBrush.Color)\">
                                <SplineColorKeyFrame KeyTime=\"00:00:00.0\" Value=\"{StaticResource FilledColor}\"/>
                                <SplineColorKeyFrame KeyTime=\"00:00:01.6\" Value=\"{StaticResource UnfilledColor}\"/>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>
                    </ControlTemplate.Resources>

                    <ControlTemplate.Triggers>
                        <Trigger Property=\"IsVisible\" Value=\"True\">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation0}\" x:Name=\"Storyboard0\" />
                                <BeginStoryboard Storyboard=\"{StaticResource Animation1}\" x:Name=\"Storyboard1\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation2}\" x:Name=\"Storyboard2\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation3}\" x:Name=\"Storyboard3\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation4}\" x:Name=\"Storyboard4\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation5}\" x:Name=\"Storyboard5\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation6}\" x:Name=\"Storyboard6\"/>
                                <BeginStoryboard Storyboard=\"{StaticResource Animation7}\" x:Name=\"Storyboard7\"/>
                            </Trigger.EnterActions>

                            <Trigger.ExitActions>
                                <StopStoryboard BeginStoryboardName=\"Storyboard0\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard1\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard2\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard3\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard4\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard5\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard6\"/>
                                <StopStoryboard BeginStoryboardName=\"Storyboard7\"/>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>

                    <Border BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Background=\"{TemplateBinding Background}\">
                        <Grid>
                            <Canvas>
                                <Canvas.Resources>
                                    <Style TargetType=\"Ellipse\">
                                        <Setter Property=\"Width\" Value=\"{Binding Path=EllipseSize}\"/>
                                        <Setter Property=\"Height\" Value=\"{Binding Path=EllipseSize}\" />
                                        <Setter Property=\"Fill\" Value=\"Transparent\" />
                                    </Style>
                                </Canvas.Resources>

                                <Ellipse x:Name=\"ellipseN\" Canvas.Left=\"{Binding Path=EllipseN.Left}\" Canvas.Top=\"{Binding Path=EllipseN.Top}\"/>
                                <Ellipse x:Name=\"ellipseNE\" Canvas.Left=\"{Binding Path=EllipseNE.Left}\" Canvas.Top=\"{Binding Path=EllipseNE.Top}\"/>
                                <Ellipse x:Name=\"ellipseE\" Canvas.Left=\"{Binding Path=EllipseE.Left}\" Canvas.Top=\"{Binding Path=EllipseE.Top}\"/>
                                <Ellipse x:Name=\"ellipseSE\" Canvas.Left=\"{Binding Path=EllipseSE.Left}\" Canvas.Top=\"{Binding Path=EllipseSE.Top}\"/>
                                <Ellipse x:Name=\"ellipseS\" Canvas.Left=\"{Binding Path=EllipseS.Left}\" Canvas.Top=\"{Binding Path=EllipseS.Top}\"/>
                                <Ellipse x:Name=\"ellipseSW\" Canvas.Left=\"{Binding Path=EllipseSW.Left}\" Canvas.Top=\"{Binding Path=EllipseSW.Top}\"/>
                                <Ellipse x:Name=\"ellipseW\" Canvas.Left=\"{Binding Path=EllipseW.Left}\" Canvas.Top=\"{Binding Path=EllipseW.Top}\"/>
                                <Ellipse x:Name=\"ellipseNW\" Canvas.Left=\"{Binding Path=EllipseNW.Left}\" Canvas.Top=\"{Binding Path=EllipseNW.Top}\"/>

                            </Canvas>
                            <Label Content=\"{Binding Path=Text}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"/>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<Border>
    <Control Style=\"{StaticResource BusyAnimationStyle}\"/>
</Border>
背后的代码(C#)
using System;
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for Spinner.xaml
    /// </summary>
    public partial class Spinner : UserControl
    {
        public int EllipseSize { get; set; } = 8;
        public int SpinnerHeight { get; set; } = 0;
        public int SpinnerWidth { get; set; } = 0;


        // start positions
        public EllipseStartPosition EllipseN { get; private set; }
        public EllipseStartPosition EllipseNE { get; private set; }
        public EllipseStartPosition EllipseE { get; private set; }
        public EllipseStartPosition EllipseSE { get; private set; }
        public EllipseStartPosition EllipseS { get; private set; }
        public EllipseStartPosition EllipseSW { get; private set; }
        public EllipseStartPosition EllipseW { get; private set; }
        public EllipseStartPosition EllipseNW { get; private set; }

        public Spinner()
        {
            InitializeComponent();
        }

        private void initialSetup()
        {
            float horizontalCenter = (float)(SpinnerWidth / 2);
            float verticalCenter = (float)(SpinnerHeight / 2);
            float distance = (float)Math.Min(SpinnerHeight, SpinnerWidth) /2;

            double angleInRadians = 44.8;
            float cosine = (float)Math.Cos(angleInRadians);
            float sine = (float)Math.Sin(angleInRadians);

            EllipseN = newPos(left: horizontalCenter, top: verticalCenter - distance);
            EllipseNE = newPos(left: horizontalCenter + (distance * cosine), top: verticalCenter - (distance * sine));
            EllipseE = newPos(left: horizontalCenter + distance, top: verticalCenter);
            EllipseSE = newPos(left: horizontalCenter + (distance * cosine), top: verticalCenter + (distance * sine));
            EllipseS = newPos(left: horizontalCenter, top: verticalCenter + distance);
            EllipseSW = newPos(left: horizontalCenter - (distance * cosine), top: verticalCenter + (distance * sine));
            EllipseW = newPos(left: horizontalCenter - distance, top: verticalCenter);
            EllipseNW = newPos(left: horizontalCenter - (distance * cosine), top: verticalCenter - (distance * sine));
        }

        private EllipseStartPosition newPos(float left, float top)
        {
            return new EllipseStartPosition() { Left = left, Top = top };
        }


        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if(e.Property.Name == \"Height\")
            {
                SpinnerHeight = Convert.ToInt32(e.NewValue);
            }

            if (e.Property.Name == \"Width\")
            {
                SpinnerWidth = Convert.ToInt32(e.NewValue);
            }

            if(SpinnerHeight > 0 && SpinnerWidth > 0)
            {
                initialSetup();
            }

            base.OnPropertyChanged(e);
        }
    }

    public struct EllipseStartPosition
    {
        public float Left { get; set; }
        public float Top { get; set; }
    }
}
样品使用
<Window x:Class=\"WpfApplication2.MainWindow\"
        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"
        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"
        xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"
        xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"
        xmlns:local=\"clr-namespace:WpfApplication2\"
        xmlns:animated=\"WpfApplication2.MainWindow\"
        mc:Ignorable=\"d\"
        Title=\"MainWindow\" Height=\"350\" Width=\"525\">

    <StackPanel Background=\"DarkGoldenrod\" Width=\"200\" Height=\"200\" VerticalAlignment=\"Top\" HorizontalAlignment=\"Left\" >
        <Button Height=\"35\">
            <Button.Content >
                <DockPanel LastChildFill=\"True\" Height=\"NaN\" Width=\"NaN\" HorizontalAlignment=\"Left\">
                    <local:Spinner EllipseSize=\"4\" DockPanel.Dock=\"Left\" HorizontalAlignment=\"Left\" Margin=\"0,0,10,5\" Height=\"16\" Width=\"16\"/>
                    <TextBlock Text=\"Cancel\" VerticalAlignment=\"Center\"/>
                </DockPanel>
            </Button.Content>
        </Button>

    </StackPanel>

</Window>
    
        您可以仅使用“图像”控件和变换来执行此操作,而无需任何其他控件和库:
<Image
    Source=\"/images/spinner.png\"
    Width=\"100\"
    Height=\"100\"
    RenderTransformOrigin=\"0.5, 0.5\" Visibility=\"{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}\">
    <Image.RenderTransform>
        <RotateTransform x:Name=\"noFreeze\" />
    </Image.RenderTransform>
    <Image.Triggers>
        <EventTrigger RoutedEvent=\"Loaded\">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation
                        Storyboard.TargetProperty=\"(Image.RenderTransform).(RotateTransform.Angle)\"
                        To=\"360\" Duration=\"0:0:1\" RepeatBehavior=\"Forever\" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Image.Triggers>
</Image>
用图像替换
/images/spinner.png
。如果要逆时针旋转将
To=\"360\"
更改为
To=\"-360\"
Duration=\"0:0:1\"
等于每旋转1秒。     
        这是一个全xaml解决方案的示例。它绑定到视图模型中的\“ IsWorking \”布尔值以显示控件并开始动画。
<UserControl x:Class=\"MainApp.Views.SpinnerView\"
         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\" 
         mc:Ignorable=\"d\" 
         d:DesignHeight=\"300\" d:DesignWidth=\"300\">

<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key=\"BoolToVisConverter\"/>
</UserControl.Resources>

<StackPanel Orientation=\"Horizontal\" Margin=\"5\"
                     Visibility=\"{Binding IsWorking, Converter={StaticResource BoolToVisConverter}}\">
    <Label>Wait...</Label>
    <Ellipse x:Name=\"spinnerEllipse\" 
                     Width=\"20\" Height=\"20\">
        <Ellipse.Fill>
            <LinearGradientBrush StartPoint=\"1,1\" EndPoint=\"0,0\" >
                <GradientStop Color=\"White\" Offset=\"0\"/>
                <GradientStop Color=\"CornflowerBlue\" Offset=\"1\"/>
            </LinearGradientBrush>
        </Ellipse.Fill>
        <Ellipse.RenderTransform>
            <RotateTransform x:Name=\"SpinnerRotate\" CenterX=\"10\" CenterY=\"10\"/>
        </Ellipse.RenderTransform>
        <Ellipse.Style>
            <Style TargetType=\"Ellipse\">
                <Style.Triggers>
                    <DataTrigger Binding=\"{Binding IsWorking}\" Value=\"True\">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard x:Name=\"SpinStoryboard\">
                                <Storyboard TargetProperty=\"RenderTransform.Angle\" >
                                    <DoubleAnimation
                                            From=\"0\" To=\"360\" Duration=\"0:0:01\"
                                            RepeatBehavior=\"Forever\" />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <StopStoryboard BeginStoryboardName=\"SpinStoryboard\"></StopStoryboard>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Ellipse.Style>
    </Ellipse>
</StackPanel>
    
        使用枚举类型指示您的ViewModel的状态
public enum ViewModeType
{
    Default, 
    Busy
    //etc.
}
然后在您的ViewModels Base类中使用一个属性
public ViewModeType ViewMode
{
    get { return this.viewMode; }
    set
    {
        if (this.viewMode != value)
        {
            this.viewMode = value;
                            //You should notify property changed here
        }
    }
}
在视图中触发ViewMode,如果它很忙,请显示busyindicator:
<Trigger Property=\"ViewMode\" Value=\"Busy\">
    <!-- Show BusyIndicator -->
</Trigger>
    
        github上的这个仓库似乎做得很好: https://github.com/blackspikeltd/Xaml-Spinners-WPF 旋转器重量轻,可以轻松放置在需要的地方。存储库中包含一个示例项目,该示例项目显示了如何使用它们。 也没有令人讨厌的代码,也没有一堆逻辑。如果需要MVVM支持,则只需将其放入具有可见性绑定的Grid中即可。     
        @Menol发布的自定义微调器有一个小问题,即微调器将向右下移动一个点的大小。我已经更新了代码,以便通过将点减去一半来补偿此偏移量。 这是更新的代码:
    private void initialSetup()
    {
        float horizontalCenter = (float)(SpinnerWidth / 2);
        float verticalCenter = (float)(SpinnerHeight / 2);
        float distance = (float)Math.Min(SpinnerHeight, SpinnerWidth) / 2;
        float dotComp = (float)(EllipseSize / 2);

        double angleInRadians = 44.8;
        float cosine = (float)Math.Cos(angleInRadians);
        float sine = (float)Math.Sin(angleInRadians);

        EllipseN = newPos(left: horizontalCenter - dotComp, top: verticalCenter - distance - dotComp);
        EllipseNE = newPos(left: horizontalCenter + (distance * cosine) - dotComp, top: verticalCenter - (distance * sine) - dotComp);
        EllipseE = newPos(left: horizontalCenter + distance - dotComp, top: verticalCenter - dotComp);
        EllipseSE = newPos(left: horizontalCenter + (distance * cosine) - dotComp, top: verticalCenter + (distance * sine) - dotComp);
        EllipseS = newPos(left: horizontalCenter - dotComp, top: verticalCenter + distance - dotComp);
        EllipseSW = newPos(left: horizontalCenter - (distance * cosine) - dotComp, top: verticalCenter + (distance * sine) - dotComp);
        EllipseW = newPos(left: horizontalCenter - distance - dotComp, top: verticalCenter - dotComp);
        EllipseNW = newPos(left: horizontalCenter - (distance * cosine) - dotComp, top: verticalCenter - (distance * sine) - dotComp);
    }
    
        CircularProgressBarBlue.xaml
<UserControl 
x:Class=\"CircularProgressBarBlue\"   
xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"
xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"
Background=\"Transparent\"
Name=\"progressBar\">
<UserControl.Resources>
    <Storyboard x:Key=\"spinning\" >
        <DoubleAnimation 
            Storyboard.TargetName=\"SpinnerRotate\" 
            Storyboard.TargetProperty=\"(RotateTransform.Angle)\"                 
            From=\"0\" 
            To=\"360\"                 
            RepeatBehavior=\"Forever\"/>
    </Storyboard>
</UserControl.Resources>
<Grid 
    x:Name=\"LayoutRoot\" 
    Background=\"Transparent\" 
    HorizontalAlignment=\"Center\" 
    VerticalAlignment=\"Center\">
    <Image Source=\"C:\\SpinnerImage\\BlueSpinner.png\" RenderTransformOrigin=\"0.5,0.5\" VerticalAlignment=\"Stretch\" HorizontalAlignment=\"Stretch\">
        <Image.RenderTransform>
            <RotateTransform 
                x:Name=\"SpinnerRotate\"
                Angle=\"0\"/>
        </Image.RenderTransform>
    </Image>


</Grid>
CircularProgressBarBlue.xaml.cs
using System;

using System.Windows;

using System.Windows.Media.Animation;


        /// <summary>
    /// Interaction logic for CircularProgressBarBlue.xaml
    /// </summary>
    public partial class CircularProgressBarBlue
    {
        private Storyboard _sb;

        public CircularProgressBarBlue()
        {
            InitializeComponent();
            StartStoryBoard();
            IsVisibleChanged += CircularProgressBarBlueIsVisibleChanged;
        }

        void CircularProgressBarBlueIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (_sb == null) return;
            if (e != null && e.NewValue != null && (((bool)e.NewValue)))
            {
                _sb.Begin();
                _sb.Resume();
            }
            else
            {
                _sb.Stop();
            }
        }

        void StartStoryBoard()
        {
            try
            {
                _sb = (Storyboard)TryFindResource(\"spinning\");
                if (_sb != null)
                    _sb.Begin();
            }
            catch
            { }
        }
    }
    

要回复问题请先登录注册