自定义循环进度微调器冻结UI

时间:2018-02-20 10:09:32

标签: c# wpf asynchronous spinner progress

我想调用webservice并获取一些数据并同时向用户显示进度微调器以避免UI冻结。我使用了自定义Progress Spinner,只在我想要显示时将其可见性设置为可见。但它会在调用Web服务部分和UI冻结后显示微调器。

自定义微调器类的CS代码

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Windows.Input;
using System.Windows.Shapes;

namespace BAFL_Intellekt.Views
{

public partial class CircularProgressBar
{
    #region Data
    private readonly DispatcherTimer animationTimer;
    #endregion

    #region Constructor
    public CircularProgressBar()
    {
        InitializeComponent();

        animationTimer = new DispatcherTimer(
            DispatcherPriority.ContextIdle, Dispatcher);
        animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 75);
    }
    #endregion

    #region Private Methods
    private void Start()
    {
        // Mouse.OverrideCursor = Cursors.Wait;
        animationTimer.Tick += HandleAnimationTick;
        animationTimer.Start();
    }

    private void Stop()
    {
        animationTimer.Stop();
        Mouse.OverrideCursor = Cursors.Arrow;
        animationTimer.Tick -= HandleAnimationTick;
    }

    private void HandleAnimationTick(object sender, EventArgs e)
    {
        SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;
    }

    private void HandleLoaded(object sender, RoutedEventArgs e)
    {
        const double offset = Math.PI;
        const double step = Math.PI * 2 / 10.0;

        SetPosition(C0, offset, 0.0, step);
        SetPosition(C1, offset, 1.0, step);
        SetPosition(C2, offset, 2.0, step);
        SetPosition(C3, offset, 3.0, step);
        SetPosition(C4, offset, 4.0, step);
        SetPosition(C5, offset, 5.0, step);
        SetPosition(C6, offset, 6.0, step);
        SetPosition(C7, offset, 7.0, step);
        SetPosition(C8, offset, 8.0, step);
    }

    private void SetPosition(Ellipse ellipse, double offset,
        double posOffSet, double step)
    {
        ellipse.SetValue(Canvas.LeftProperty, 50.0
            + Math.Sin(offset + posOffSet * step) * 50.0);

        ellipse.SetValue(Canvas.TopProperty, 50
            + Math.Cos(offset + posOffSet * step) * 50.0);
    }

    private void HandleUnloaded(object sender, RoutedEventArgs e)
    {
        Stop();
    }

    private void HandleVisibleChanged(object sender,
        DependencyPropertyChangedEventArgs e)
    {
        bool isVisible = (bool)e.NewValue;

        if (isVisible)
            Start();
        else
            Stop();
    }
    #endregion
}
}

的Xaml

    <UserControl x:Class="BAFL_Intellekt.Views.CircularProgressBar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="Auto" Width="Auto" Background="Transparent"
             IsVisibleChanged="HandleVisibleChanged">
    <Grid x:Name="LayoutRoot" Background="Transparent"
          ToolTip="Searching...."
          HorizontalAlignment="Center"
          VerticalAlignment="Center">
        <Canvas RenderTransformOrigin="0.5,0.5"
                HorizontalAlignment="Center"
             VerticalAlignment="Center" Width="120"
             Height="120" Loaded="HandleLoaded"
                Unloaded="HandleUnloaded"  >
            <Ellipse x:Name="C0" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="1.0"/>
            <Ellipse x:Name="C1" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.9"/>
            <Ellipse x:Name="C2" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.8"/>
            <Ellipse x:Name="C3" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.7"/>
            <Ellipse x:Name="C4" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.6"/>
            <Ellipse x:Name="C5" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.5"/>
            <Ellipse x:Name="C6" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.4"/>
            <Ellipse x:Name="C7" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.3"/>
            <Ellipse x:Name="C8" Width="20" Height="20"
                     Canvas.Left="0"
                     Canvas.Top="0" Stretch="Fill"
                     Fill="Black" Opacity="0.2"/>
            <Canvas.RenderTransform>
                <RotateTransform x:Name="SpinnerRotate"
                     Angle="0" />
            </Canvas.RenderTransform>
        </Canvas>
    </Grid>
</UserControl>

Xaml在其他用户控件中使用微调器

<Viewbox x:Name="Spinner" Visibility="Hidden" Width="200" Height="200" Panel.ZIndex="5"
                HorizontalAlignment="Center"
                VerticalAlignment="Center">
            <local:CircularProgressBar />
        </Viewbox>

并在想要在UI中显示微调器时将visibilty设置为true

Spinner.Visibility = Visibility.Visible;

1 个答案:

答案 0 :(得分:1)

private void HandleLoaded(object sender, RoutedEventArgs e)
{
    Application.Current.Dispatcher.BeginInvoke(
        DispatcherPriority.Background,
        new Action(() => changeRotation(...))); // wrap original HandleLoaded logic 

}