The goal is to display the information that the application is working. So I\'m looking for an intelligent implementation sample of a loading spinner using WPF / MVVM.
Here's an example of an all-xaml solution. It binds to an "IsWorking" boolean in the viewmodel to show the control and start the animation.
<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>
</UserControl>
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
{ }
}
}
Check out the BusyIndicator in the extended WPF Toolkit.
I wrote this user control which may help, it will display messages with a progress bar spinning to show it is currently loading something.
<ctr:LoadingPanel x:Name="loadingPanel"
IsLoading="{Binding PanelLoading}"
Message="{Binding PanelMainMessage}"
SubMessage="{Binding PanelSubMessage}"
ClosePanelCommand="{Binding PanelCloseCommand}" />
It has a couple of basic properties that you can bind to.
This repo on github seems to do the job quite well:
https://github.com/blackspikeltd/Xaml-Spinners-WPF
The spinners are all light weight and can easily be placed wherever needed. There is a sample project included in the repo that shows how to use them.
No nasty code-behinds with a bunch of logic either. If MVVM support is needed, one can just take these and throw them in a Grid with a Visibility binding.
A very simple "plug and play" spinner could be one of the spinning icons from the Font Awesome Wpf Package (Spinning icons).
The usage is quite simple, just install the nuget package:
PM> Install-Package FontAwesome.WPF
Then add the reference to the namespace
xmlns:fa="http://schemas.fontawesome.io/icons/"
and use the ImageAwesome control. Set the Spin="True" property and select one of the "Spinner", "Refresh", "Cog" and "CircleOutlinedNotched" Icon. It's scalable and can be resized by setting width and height.
<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>