【WPF學習】第三十一章 WPF命令模型


  WPF命令模型由許多可變的部分組成。總之,它們都具有如下4個重要元素:

  •   命令:命令表示應用程序任務,並且跟蹤任務是否能夠被執行。然而,命令實際上不包含執行應用程序任務的代碼。
  •   命令綁定:每個命令綁定針對用戶界面的具體區域,將命令連接到相關的應用程序邏輯。這種分解的設計是非常重要的,因為單個命令可用於應用程序中的多個地方,並且在每個地方具有不同的意義。為處理這一問題,需要將同一命令與不同的命令綁定。
  •   命令源:命令源觸發命令。例如,MenuItem和Button都是命令源。單擊它們都會執行綁定命令。
  •   命令目標:命令目標是在其中執行命令的元素。例如,Paste命令可在TextBox控件中插入文本,而OpenFile命令可在DocumentViewer中打開文檔。根據命令的本質,目標可能很重要,也可能不重要。

一、ICommand接口

  WPF命令模型的核心是System.Windows.Input.ICommand接口,該接口定義了命令的工作原理。該接口包含兩個方法和一個事件:

public interface ICommand
{
    void Execute(object parameter);
    bool CanExecute(object parameter);

    event EventHandler CanExecuteChanged;
}

  在一個簡單實現中,Execute()方法將包含應用程序任務邏輯(例如,打印文檔)。然而,正如下一節中將看到,WPF的實現更復雜。它使用Execute()方法引發一個更復雜的過程,該過程最終觸發在應用程序其他地方處理的事件。通過這種方式可以使用預先准備好的命令類,並插入自己的邏輯。還可以靈活地再幾個不同地方使用同一個命令(如Print命令)。

  CanExecute()方法返回命令的狀態——如果命令可用,就返回true;如果不可用,就返回false。Execute()和CanExecute()方法都接受一個附加的參數對象,可使用該對象傳遞所需的任何附加信息。

  最初,當命令狀態改變時引發CanExecuteChanged事件。對於使用命令的任何事件,這是指示信號,表示它們應當調用CanExecute()方法檢查命令的狀態。通過使用該事件,當命令可用時,命令源(如Button或MenuItem)可自動啟用自身;當命令不可用時,禁用自身。

二、RoutedCommand類

  當創建自己的命令時,不會直接實現ICommand接口;而是使用System.Windows.Input.RoutedCommand類,該類自動實現了ICommand接口。RoutedCommand類是WPF中唯一實現了ICommand接口的類。換句話說,所有WPF命令都是RoutedCommand類及其派生類的實例。

  在WPF命令模型背后的一個重要概念是,RoutedCommand類不包含任何應用程序邏輯,而只代表命令,這意味着各個RoutedCommand對象具有相同的功能。

  RoutedCommand類為事件冒泡和隧道添加了一些額外的基礎結構。鑒於ICommand接口封裝了命令的思想——可被觸發的動作並可被啟用或禁用——RoutedCommand類對命令進行了修改,使命令可在WPF元素層次結構中冒泡,以便獲得正確的事件處理程序。

  為支持路由事件,RoutedCommand類私有地實現了ICommand接口,並添加了ICommand接口方法的一些不同版本。最明顯的變化是,Execute()和CanExecute()方法使用了一個額外參數。下面的新的簽名:

public void Execute(object parameter,IInputElement target)
{
    //...
}

public void CanExecute(object parameter,IInputElement target)
{
    //...
}

  參數target是開始處理事件的元素。事件從target元素開始,然后冒泡至高層的容器,直到應用程序為了執行合適的任務而處理了事件(為了處理Executed事件,元素還需要借助於另一個類——CommandBinding類的幫助)。

  除上面的修改外,RoutedCommand類還引入了三個屬性:命令名稱(Name屬性)、包含命令的類(OwnerType)以及任何可用於觸發命令的按鍵或鼠標操作(位於InputGestures集合中)。

三、RoutedUICommand類

  在程序中處理的大部分命令不是RoutedCommand對象,而是RoutedUICommand類的實例,RoutedUICommand類繼承自RoutedCommand類(實際上,WPF提供的所有預先構建好的命令都是RoutedUICommand對象)。

  RoutedUICommand類用於具有文本的命令,這些文本顯示在用戶界面中的某些地方(例如菜單項文本、工具欄按鈕的工具欄提示)。RoutedUICommand類只添加了Text屬性,該屬性是為命令顯示的文本。

  為命令定義命令文本(而不是直接在控件上定義文本)的優點是可在某個位置執行本地化。但如果命令文本永遠不會在用戶界面的任何地方顯示,那么RoutedUICommand類和RoutedCommand類是等效的。

四、命令庫

  WPF設計者認識到,每個應用程序可能都有大量命令,並且對於許多不同的應用程序,很多命令時通用的,例如,所有基於文檔的應用程序都有他們自己版本的New、Open以及Save命令。為減少創建這些命令所需的工作,WPF提供了基本命令庫,基本命令庫中保存的命令超過100條。這些命令通過以下5個專門的靜態類的屬性提供:

  •   ApplicationCommands:該類提供了通用命令,包括剪貼板命令(如Copy、Cut和Paste)以及文檔命令(如New、Open、Save、SaveAs和Print等)。
  •   NavigationCommands:該類提供了用於導航的命令,包括為基於頁面的應用程序設計的一些命令(如BrowseBack、BrowSeForward和NextPage),以及其他適合於基於文檔的應用程序的命令(如IncreaseZoom和Refresh).
  •   EditingCommands:該類提供了許多重要的文檔編輯命令,包括用於移動的命令(MoveToLineEnd、MoveLeftByWord和MoveUpByPage等),選擇內容的命令(SelectToLineEnd、SelectLeftByWord),以及改變格式的命令(ToggleBold和ToggleUnderLine)。
  •   ComponentCommands:該類提供了由用戶界面組件使用的命令,包括用於移動和選擇內容的命令,這些命令和EditingCommands類中的一些命令類似(甚至完全相同)。
  •   MediaCommands:該類提供了一組用於處理多媒體的命令(如Play、Pause、NextTrack以及IncreaseVolume).

  ApplicationCommands類提供了一組基本命令,在所有類別的應用程序中都經常會用到這些命令,所以在此簡單介紹一下。下面列出了所有這些命令。

New Copy SelectAll
Open Cut Stop
Save Paste ContextMenu

SaveAs

Delete CorrectionList
Close Undo Properties
Print Redo Help
PrintPreview Find  
CancelPrint Replace  

  例如,ApplicationCommands.Open是提供RoutedUICommand對象的靜態屬性,該對象表示應用程序中的Open命令。因為ApplicationCommands.Open是靜態屬性,所以在整個應用程序中只有一個Open命令實例。然而,根據命令源的不同(換句話說,是在用戶界面的什么地方觸發的該命令),可采用不同的處理方式。

  每個命令的RoutedUICommand.Text屬性和名稱是相互匹配的,指示在單詞之間添加了空格。例如,ApplicationCommands.SelectedAll命令的文本時SelecteAll(Name屬性使用相同的沒有空格的文本)。因為Open命令時ApplicationCommands類的靜態屬性,所以RoutedUICommand.OwnerType屬性返回ApplicationCommands類的類型對象。

  這些單獨的命令對象僅時一些標志起,不具有實際功能。然而,許多命令對象都有一個額外的特征:默認輸入綁定。例如,ApplicationCommands.Open命令被映射到Ctrl+O快捷鍵。只要將命令綁定到命令源,並為窗口添加命令源,這個快捷鍵就會被激活,即使沒有在用戶界面的任何地方顯示該命令也同樣如此。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM