1

I've tried many things to du that, but none are working. Let me explain:

this is how my app works: I click on buttons, it call methods with http requests. The request are all synchronous.

button click -> set loading visual to Visible -> http request in the same method -> http request finished-> set loading visual to Collapsed.

This is the code example :

    public static StackPanel loading ;

    public static void setLoading()
    {
        MyStaticValues.loading.Visibility = Visibility.Visible;
        MyStaticValues.loading.UpdateLayout();
    }

    public static void setUnLoading()
    {
        MyStaticValues.loading.Visibility = Visibility.Collapsed;
        MyStaticValues.loading.UpdateLayout();
    }

...

        MyStaticValues.loading = this.spinner;
        MyStaticValues.loading.InvalidateVisual();


... 

...

// http request method -on click- 
    MyStaticValues.setLoading();
    ..do HTTP request..
    // after success ->
    MyStaticValues.setUnLoading();

..end..

It always go into the setLoading/ setUnLoading methods, but the UI is never refresh. As i Said, The request are all synchronous. The problem is probably from this, But I would like to keep the request on synchronous if possible..

any idea?

Ghasem
  • 14,455
  • 21
  • 138
  • 171
F4Ke
  • 1,631
  • 1
  • 20
  • 49

2 Answers2

0

The problem is that you are doing the three methods (setLoading, do http and setUnloading) while handling a UI request. This is done on the one and only UI thread.

There is no re-draw or painting happening until after you have returned from the button click event.

To get the desired effect you would have to do the http loading in an asynchronous fashion:

protected override void OnClick(object sender, EventArgs args)
{
   Thread worker = new Thread(HandleOnClick);
   worker.Start();
}

private void HandleOnClick()
{
    Invoke(setLoading); // this will execute on the UI thread
    // do http stuff this happens when you do it

    Invoke(setUnloading); // This will execute on the UI thread as well
}
Jens Meinecke
  • 2,904
  • 17
  • 20
0

If you want to keep your application as more synchronous as possible, you can emulate in WPF the DoEvents method for Windows Form. You just need a simple helper class:

public class UIHelper
{
    private delegate void VoidHandler();

    public static void DoEvents()
    {
        Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new VoidHandler(delegate { }));
    }
}

Then in your click event handler you can write something like that:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Button button = (Button)sender;
    button.Content = "I'm starting to perform a long task!";

    UIHelper.DoEvents();

    // Next code line simulate your synchronous http request
    // Let's suppose it lasts 10 seconds...
    Thread.Sleep(1000 * 10);

    button.Content = "I'm ok now!";
}

This is not my favourite solution - I agree that an async http request would be better - but it allows you to keep your application synchronous.

Il Vic
  • 5,576
  • 4
  • 26
  • 37