4

I have a WPF C# app.

I am using the Xceeed.wpf toolkit

In pseudo code, my function will:

  • Display the BusyIndicator
  • A REST API call is made to my server
  • the BusyIndicator stops displaying

What actually happens is that the BusyIndicator does not display until the REST API call has finished. Sometimes it does display but the 'marque' affect is not fluid.

I have tried several approaches and this is my latest attempt:

// raise event to invoke method call on main UI page
// event raised here

Task.Run(() =>
{
    // makes API call
    busyIndicator.IsBusy = false;

);

public void ShowBusy()
{
    this.InvokeOnMainThread(() =>
    {
        busyIndicator.IsBusy = true;
    });
}

public static void InvokeOnMainThread(this Control control, Action method)
{
    if (!control.Dispatcher.CheckAccess())
    {            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method);
        return;
    }
    method();
}

markup:

    <xctk:BusyIndicator Name="busyIndicator" Grid.Column="1" Grid.Row="1" IsBusy="True" DisplayAfter="0" Background="White" BorderBrush="White">
        <xctk:BusyIndicator.BusyContentTemplate  >
            <DataTemplate>
                <StackPanel Height="50">
                    <TextBlock HorizontalAlignment="Center">Please wait...</TextBlock>
                    <WPFSpark:FluidProgressBar  Oscillate="True" Width="400"   Foreground="DarkGreen" BorderBrush="White" Opacity="1" />
                </StackPanel>                 
            </DataTemplate>
        </xctk:BusyIndicator.BusyContentTemplate>
        <xctk:BusyIndicator.OverlayStyle>
            <Style TargetType="Rectangle">
                <Setter Property="Fill" Value="White"/>                    
            </Style>
        </xctk:BusyIndicator.OverlayStyle>
        <xctk:BusyIndicator.ProgressBarStyle>
            <Style TargetType="ProgressBar">
                <Setter Property="BorderBrush" Value="white"></Setter>
                <Setter Property="Visibility" Value="Collapsed"/>
            </Style>
        </xctk:BusyIndicator.ProgressBarStyle>
        <xctk:BusyIndicator.Content>
               //my usercontrol which invokes the call
        </xctk:BusyIndicator.Content>
</xctk:BusyIndicator>
Nishi
  • 10,634
  • 3
  • 27
  • 36
Andrew Simpson
  • 6,883
  • 11
  • 79
  • 179
  • You should wrap access to the `busyIndicator.IsBusy` property with a call to `Dispatcher.BeginInvoke` (or you `await` the `Task.Run()` and set your busy state afterwards), as you aren't allowed to access the ui from any other than the ui thread. – Franz Wimmer Feb 11 '16 at 13:49
  • is it MVVM or code - behind application? – StepUp Feb 11 '16 at 13:51
  • @StepUp Iwas using the dispatcher but omitted in my question to make it clearer which i now see was an error – Andrew Simpson Feb 11 '16 at 13:53

1 Answers1

6

You've to wait till the Task is completed before setting the BusyIndicator off. At the moment you're just firing off the Task and setting the busy indicator to off.

Mark your method async and await for the API call.

busyIndicator.IsBusy = true;
await Task.Run(() =>
{
    //makes api call
);
busyIndicator.IsBusy = false;

If.. For some reason, you cant use async/await, then use continuation.

  Task.Run(() =>
  {
      //makes api call
  }).ContinueWith(antecedent =>
  {
      busyIndicator.IsBusy = false;
  }, TaskScheduler.FromCurrentSynchronizationContext());
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189