按代码刷新WPF-Control
我试图禁用一个按钮,拒绝垃圾邮件点击此按钮。
我使用了一个Refresh委托来渲染调用控件,但它显示为已启用。 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; }
由于所有这些似乎都发生在UI-Thread上,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();
更好的是,为什么不使用ICommand绑定而不是乱搞事件,你可以实现CanExecute,你可以根据你是否要启用/禁用按钮返回true / false
这是ICommand的一个很好的例子
您正在将方法的优先级设置为“渲染”,而实际上并不进行任何渲染。
我想说使用异步调用将是最好的操作,给布局引擎时间渲染:
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); }