我正在構建一個使用MVVM設計模式的應用程序,並且想要使用ApplicationCommands類中定義的RoutedUICommands。由於View(讀UserControl)的CommandBindings屬性不是DependencyProperty,因此我們無法直接將ViewModel中定義的CommandBindings綁定到View。我通過定義一個抽象的View類來解決這個問題,它通過一個ViewModel接口確保每個ViewModel具有一個CommandBindings的ObservableCollection,從而以編程方式綁定這個類。這一切都很好,但是,在某些情況下,我想要執行在不同類(View和ViewModel)相同的命令中定義的邏輯。例如,保存文檔時。RoutedUICommand Preview執行的Bug?
在視圖模型的代碼將文檔保存到磁盤:
private void InitializeCommands()
{
CommandBindings = new CommandBindingCollection();
ExecutedRoutedEventHandler executeSave = (sender, e) =>
{
document.Save(path);
IsModified = false;
};
CanExecuteRoutedEventHandler canSave = (sender, e) =>
{
e.CanExecute = IsModified;
};
CommandBinding save = new CommandBinding(ApplicationCommands.Save, executeSave, canSave);
CommandBindings.Add(save);
}
乍一看前面的代碼是所有我想做的事,但在查看文本框到了該文檔的約束,只有更新它的來源,當它失去了重點。但是,通過按Ctrl + S,我可以保存文檔而不會丟失焦點。這意味着文檔在源代碼中更新之前保存,有效地忽略了更改。但由於出於性能原因將UpdateSourceTrigger更改爲PropertyChanged不是可行的選項,因此其他內容必須在保存前強制更新。所以我想,讓使用PreviewExecuted事件迫使更新的PreviewExecuted事件,像這樣:
//Find the Save command and extend behavior if it is present
foreach (CommandBinding cb in CommandBindings)
{
if (cb.Command.Equals(ApplicationCommands.Save))
{
cb.PreviewExecuted += (sender, e) =>
{
if (IsModified)
{
BindingExpression be = rtb.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
}
e.Handled = false;
};
}
}
然而,分配一個處理程序的PreviewExecuted事件似乎完全取消的情況下,甚至當我明確地設置將屬性處理爲false。所以我在之前的代碼示例中定義的executeSave事件處理程序不再執行。請注意,當我將cb.PreviewExecuted更改爲cb.Executed代碼時,執行但未按正確的順序執行。
我認爲這是.Net中的一個Bug,因爲您應該能夠向PreviewExecuted和Executed添加一個處理程序,並按順序執行它們,前提是您不要將該事件標記爲已處理。
任何人都可以證實此行爲?或者我錯了?有沒有解決這個Bug的方法?
情況越來越複雜......所以,我看着你提到的源代碼和他們做同樣的OnCanExecute與PreviewCanExecute中的東西。但是,OnCanExecute的CanExecuteRoutedEventArgs和OnExecuted的ExecutedRoutedEventArgs之間存在重要的區別。正如你所期望的那樣,CanExecuteRoutedEventArgs包含一個ContinueRouting屬性,它正是這樣做的,但由於某種原因,ExecutedRoutedEventArgs必須不做。我真的無法從微軟那裏得到我的選擇。 – elmar 2010-02-23 10:06:36
我認爲ContinueRouting不參與該過程 - 請參閱我的編輯2的帖子。 至於他們爲什麼這樣做...看看CommandBinding.OnExecuted()方法的兩部分,它們幾乎完全一樣 - 它可能是複製/粘貼的經典案例:)然後它是一個錯誤。說真的,我不認爲是這樣。 我真的很想知道他們背後的原因是什麼。 – 2010-02-23 19:04:23