通过代码刷新WPF控件

3

我正在尝试禁用一个按钮,以避免对该按钮进行垃圾点击。

我使用了Refresh委托来Render调用控件,但按钮仍然是启用状态。 connect()方法需要大约4秒钟,在此期间按钮将显示为启用状态。

问题出在哪里?

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;
}
3个回答

4

由于所有在UI线程上发生的事情都没有时间更新,因此您需要在后台线程上运行任务,并在完成后再次更改UI(例如使用已经具有RunWorkerCompleted事件的BackgroundWorker)。

例如:

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

+1 我在 Stack Overflow 上看到了很多关于这个问题的答案。这是我见过的最灵活和可靠的答案。 - Chris Schiffhauer

1

我的投票在这里。永远不要以老式风格管理WPF UI。 - Mario Vernari
更多的代码来管理 UI 状态,而 WPF 已经有了很好的 ICommand 绑定! - Bek Raupov

0

您正在将一个方法的优先级设置为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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接