2011-07-27 73 views
3

我想禁用一个按钮来拒绝点击此按钮上的垃圾邮件。刷新WPF控制代码

我使用了一个Refresh委托Render调用该控件,但它显示为启用。 connect() - Methode在按钮显示为启用时需要约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; 
} 

回答

4

由于出现都对发生UI多线程的UI没有时间更新在两者之间,你需要在后台线程运行的任务和完成再次更改UI(例如使用BackgroundWorker已经有RunWorkerCompleted事件)。

例如

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

+1我见过很多答案对这个问题的SO。这是我见过的最灵活可靠的。 –

0

您正在设置渲染方法的优先级,它实际上没有进行渲染。

我会说使用异步调用将是最好的行动来这里拿,给布局引擎的渲染时间:

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); 
} 
1

甚至更​​好,而不是用事件乱搞,为什么不使用的ICommand绑定在那里你可以实现CanExecute您可以返回真/假取决于你是否要启用/禁用按钮

Great example here on ICommand

+0

我的投票在这里。永远不要以旧式的风格管理WPF界面。准确地说是 –

+0

。更多的代码来管理UI状态,WPF已经有了很好的ICommand绑定! –