Destructor
Destructor

Reputation: 1771

Refresh WPF-Control by code

I am trying to disable a button for denying a spam click on this button.

I used a Refresh delegate to Render invoke the control but it appears as enabled. The connect()-Methode is taking about 4 seconds in witch the button is shown as enabled.

Where is the problem ?

public static class ExtensionMethods
{

   private static Action EmptyDelegate = delegate() { };


   public static void Refresh(this UIElement uiElement)
   {
      uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
   }
}


private void buttonConnect_Click(object sender, RoutedEventArgs e)
{
    this.Cursor = Cursors.Wait;
    buttonConnect.IsEnabled = false;
    buttonConnect.Refresh();

    if (buttonConnect.Content.Equals("Connect"))
    {
        connect();
    }
    else
    {
        disconnect();
    }
    buttonConnect.IsEnabled = true;
    buttonConnect.Refresh();
    this.Cursor = Cursors.Arrow;
}

Upvotes: 3

Views: 10133

Answers (3)

Bek Raupov
Bek Raupov

Reputation: 3777

even better, instead of messing around with events, why not use ICommand binding and there you can implement CanExecute which you can return true/false depending on whether you want to enable/disable the button

Great example here on ICommand

Upvotes: 1

brunnerh
brunnerh

Reputation: 184506

Since all that appears to happen on the UI-Thread the UI has no time to update in-between, you need to run your task on a background thread and change the UI again on completion (e.g. use a BackgroundWorker which already has a RunWorkerCompleted event).

e.g.

button.IsEnabled = false;
var bw = new BackgroundWorker();
bw.DoWork += (s, _) =>
{
    //Long-running things.
};
bw.RunWorkerCompleted += (s,_) => button.IsEnabled = true;
bw.RunWorkerAsync();

Upvotes: 4

Bas
Bas

Reputation: 27095

You are setting the priority of a method to Render, which does not actually do any rendering.

I would say using an asynchronous call would be the best action to take here, giving the layout engine time to render:

private void buttonConnect_Click(object sender, RoutedEventArgs e)
{
    this.Cursor = Cursors.Wait; 
    buttonConnect.IsEnabled = false; 

    Action action = buttonConnect.Content.Equals("Connect") ? connect : disconnect;

    new Action(() => {
        action();
        Dispatcher.Invoke(() =>
            {
                buttonConnect.IsEnabled = true;
                this.Cursor = Cursors.Arrow;
            });
    }).BeginInvoke(null, null);
}

Upvotes: 0

Related Questions