轉https://www.cnblogs.com/zjoch/p/3647236.html
WPF: 使用CommandManager.InvalidateRequerySuggested手動更新Command狀態
WPF判斷命令(Command)是否能夠執行是通過ICommand.CanExecute事件,在實際程序中路由命令一般是通過CommandBinding來使命令得到實際操作代碼,但是這個CanExecute事件的調用是由WPF控制的,有些時候,比如命令執行後進行一些異步耗時操作,操作完成後會影響CanExecute事件結果,但是WPF不會立即做出反應,那麼這個時侯就需要手動調用CommandManager.InvalidateRequerySuggested對命令系統進行一次刷新。
比如下面這個小程序
<Window.CommandBindings> <CommandBinding Command="New" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed" /> </Window.CommandBindings> <StackPanel> <Button Command="New">執行工作</Button> <TextBlock Name="tbl" Text="等待執行"></TextBlock> </StackPanel>
事件執行:
// // 事件執行代碼 // privatevoid CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute =!finished; } privatevoid CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { System.Threading.ThreadPool.QueueUserWorkItem(dowork); } bool finished =false; void dowork(object obj) { updateUI("開始工作"); System.Threading.Thread.Sleep(1000); updateUI("工作結束"); finished =true; } void updateUI(string msg) { Dispatcher.BeginInvoke((Action)(() => tbl.Text = msg)); }
程序按鈕點擊後下面文字顯示“工作結束”,這時按鈕理應是禁用的(因爲此時CanExecute結果是false),但實際上按鈕沒有被禁用,只有界面發生改變後(如焦點,按鍵變化,或者按鈕再次被點擊),按鈕纔會被禁用,因爲此時WPF才調用相應的CanExecute事件。
手動調用CommandManager.InvalidateRequerySuggested就可以解決問題,注意這個函數只有在UI主線程下調用纔會起作用。
void dowork(object obj) { updateUI("開始工作"); System.Threading.Thread.Sleep(1000); updateUI("工作結束"); finished =true; //手動更新 updateCommand(); } void updateCommand() { Dispatcher.BeginInvoke((Action)(() =>CommandManager.InvalidateRequerySuggested())); }