I need something very simple like just show loading process without progress. Like user click on button and process start it takes 5 sec for this time I would like to show to user progress implementation like this
I tried to find how to implement this, but actually what I found is people build a complete libraries or heavy xaml animation implementation. Actually I thought it should be something simple out of the box option like put in xaml Progress bar
and in cs file when you need call myProgressBar.Show()
or myProgressBar.Hide()
.
That it, I don't need to implement libraries or 200 hundreds lines in my xaml.
How to make this simple implementation?
There is no native WPF control to produce such a display, so you're going to need some code (in a library) that you can use as required. The amount of code depends on just how much flexibility you require for the control.
Here's my version - designed to give some options for the display, but ensures minimal use of system resources, and stops any processing once no longer in use.
<UserControl
x:Class="Peregrine.WPF.View.Controls.perBusySpinner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:Peregrine.WPF.View.Controls"
Width="{Binding RelativeSource={RelativeSource Self}, Path=Height, Mode=TwoWay}"
Height="120">
<Viewbox
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:perBusySpinner}}}">
<Canvas
Width="{Binding Path=Diameter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:perBusySpinner}}}"
Height="{Binding Path=Diameter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:perBusySpinner}}}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Transparent"
RenderTransformOrigin="0.5,0.5"
UseLayoutRounding="False">
<Canvas.Resources>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:perBusySpinner}}}" />
<Setter Property="Height" Value="{Binding Path=ItemDiameter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:perBusySpinner}}}" />
<Setter Property="Stretch" Value="Fill" />
<Setter Property="StrokeThickness" Value="0" />
<Setter Property="Width" Value="{Binding Path=ItemDiameter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:perBusySpinner}}}" />
</Style>
</Canvas.Resources>
<Ellipse
x:Name="Item1"
Opacity="1.0" />
<Ellipse
x:Name="Item2"
Opacity="0.92" />
<Ellipse
x:Name="Item3"
Opacity="0.84" />
<Ellipse
x:Name="Item4"
Opacity="0.76" />
<Ellipse
x:Name="Item5"
Opacity="0.68" />
<Ellipse
x:Name="Item6"
Opacity="0.60" />
<Ellipse
x:Name="Item7"
Opacity="0.52" />
<Ellipse
x:Name="Item8"
Opacity="0.44" />
<Ellipse
x:Name="Item9"
Opacity="0.36" />
<Ellipse
x:Name="Item10"
Opacity="0.28" />
<Ellipse
x:Name="Item11"
Opacity="0.20" />
<Ellipse
x:Name="Item12"
Opacity="0.12" />
<Canvas.RenderTransform>
<RotateTransform x:Name="SpinnerRotateTransform" Angle="0" />
</Canvas.RenderTransform>
</Canvas>
</Grid>
</Viewbox>
</UserControl>
.
public partial class perBusySpinner
{
private readonly DispatcherTimer _spinnerTimer;
// the nominal size of the spinner - the actual size is determined by the Width / Height as the spinner is contained within a ViewBox
public double Diameter => 100.0;
public double ItemDiameter => Diameter / 6.0;
public double ItemRadius => ItemDiameter / 2.0;
public double ItemPositionRadius => (Diameter - ItemDiameter) / 2.0;
public perBusySpinner()
{
InitializeComponent();
_spinnerTimer = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher);
_spinnerTimer.Tick += (s, e) => SpinnerRotateTransform.Angle = (SpinnerRotateTransform.Angle + 30) % 360;
Loaded += (s, e) => OnLoaded();
Unloaded += (s, e) => Stop();
IsVisibleChanged += (s, e) => OnIsVisibleChanged((bool)e.NewValue);
}
/// <summary>
/// IsVisibleChanged also covers the case where the spinner is placed inside another control which itself is collapsed or hidden
/// </summary>
/// <param name="isVisible">
/// </param>
private void OnIsVisibleChanged(bool isVisible)
{
// disable spinning in the Visual Studio designer
if (perViewModelHelper.IsInDesignMode)
return;
if (isVisible)
Start();
else
Stop();
}
/// <summary>
/// Rotations per minute
/// </summary>
public int Speed
{
get => (int)GetValue(SpeedProperty);
set => SetValue(SpeedProperty, value);
}
public static readonly DependencyProperty SpeedProperty =
DependencyProperty.Register("Speed", typeof(int), typeof(perBusySpinner), new PropertyMetadata(60));
private void OnLoaded()
{
SetItemPosition(Item1, 0);
SetItemPosition(Item2, 1);
SetItemPosition(Item3, 2);
SetItemPosition(Item4, 3);
SetItemPosition(Item5, 4);
SetItemPosition(Item6, 5);
SetItemPosition(Item7, 6);
SetItemPosition(Item8, 7);
SetItemPosition(Item9, 8);
SetItemPosition(Item10, 9);
SetItemPosition(Item11, 10);
SetItemPosition(Item12, 11);
}
private void SetItemPosition(DependencyObject item, int index)
{
item.SetValue(Canvas.LeftProperty, Diameter / 2.0 + (Math.Sin(Math.PI * (index / 6.0)) * ItemPositionRadius) - ItemRadius);
item.SetValue(Canvas.TopProperty, Diameter / 2.0 + (Math.Cos(Math.PI * (index / 6.0)) * ItemPositionRadius) - ItemRadius);
}
private void Stop()
{
_spinnerTimer.Stop();
}
private void Start()
{
// each tick of the timer is 1 step of revolution
_spinnerTimer.Interval = TimeSpan.FromMilliseconds(60000 / (12.0 * Speed));
_spinnerTimer.Start();
}
}
Once defined in a library, usage of such a control only required a minimal amount of xaml.
<vctrl:perBusySpinner
Width="32"
Background="Transparent"
Foreground="Blue" />
To show and activate the spinner, just set it's Visibilty
property to Visible or bind to a boolean property in the ViewModel via a BooleanToVisibility
converter.
More detail at my blog post .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.