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)(() […]
View Details做过WinForm开发的都会郁闷WPF竟然没有Timer。 今天想在WPF中用Timer可是发现WPF没有Timer类,找了半天发现新增了一个 DispatcherTimer确实好用和WinForm中Timer用法相似。 —————————————————————————————————————————-- 引:银光中国 在 WPF 中不再有类似 WinForm 中的 Timer 控件,因此,需要使用 DispatcherTimer 类来实现类似 Timer 的定时执行事件,该事件使用委托方式实现。DispatcherTimer 类 在 System.Windows.Threading 下,需要 using System.Windows.Threading 命名空间。 MSDN事例: 创建了名为 dispatcherTimer 的 DispatcherTimer 对象。 事件处理程序 dispatcherTimer_Tick 被添加到 dispatcherTimer 的 Tick 事件中。 使用 TimeSpan 对象将 Interval 设置为 1 秒,并启动了计时器。
1 |
<ol class="dp-c"><li class="alt"><span><span class="comment">// DispatcherTimer setup</span><span> </span></span></li><li><span>dispatcherTimer = <span class="keyword">new</span><span> System.Windows.Threading.DispatcherTimer(); </span></span></li><li class="alt"><span>dispatcherTimer.Tick += <span class="keyword">new</span><span> EventHandler(dispatcherTimer_Tick); </span></span></li><li><span>dispatcherTimer.Interval = <span class="keyword">new</span><span> TimeSpan(0,0,1); </span></span></li><li class="alt"><span>dispatcherTimer.Start(); </span></li></ol> |
Tick 事件处理程序将更新显示当前秒数的 Label,并且它将对 CommandManager 调用 InvalidateRequerySuggested。
1 |
<ol class="dp-c"><li class="alt"><span><span class="comment">// System.Windows.Threading.DispatcherTimer.Tick handler</span><span> </span></span></li><li><span> <span class="comment">//</span><span> </span></span></li><li class="alt"><span> <span class="comment">// Updates the current seconds display and calls</span><span> </span></span></li><li><span> <span class="comment">// InvalidateRequerySuggested on the CommandManager to force </span><span> </span></span></li><li class="alt"><span> <span class="comment">// the Command to raise the CanExecuteChanged event.</span><span> </span></span></li><li><span> <span class="keyword">private</span><span> </span><span class="keyword">void</span><span> dispatcherTimer_Tick(</span><span class="keyword">object</span><span> sender, EventArgs e) </span></span></li><li class="alt"><span> { </span></li><li><span> <span class="comment">// Updating the Label which displays the current second</span><span> </span></span></li><li class="alt"><span> lblSeconds.Content = DateTime.Now.Second; </span></li><li><span> </span></li><li class="alt"><span> <span class="comment">// Forcing the CommandManager to raise the RequerySuggested event</span><span> </span></span></li><li><span> CommandManager.InvalidateRequerySuggested(); </span></li><li class="alt"><span> } </span></li></ol> |
转自:http://www.cnblogs.com/midcn/archive/2011/03/18/1987928.html
View Details