2017年12月19日 星期二

WPF Command

Ref:

https://eric0806.blogspot.tw/2013/07/wpf-custom-command.html


關鍵
<Window.CommandBindings>
    <CommandBinding
        Command="{StaticResource Quit}"
        CanExecute="Quit_CanExecute"
        Executed="Quit_Executed" />
</Window.CommandBindings>


=================================================


WPF建立自訂的Command

WPF強大的功能之一,是提供了一些系統預設Command,及可以讓使用者自訂Command的功能。

什麼是Command(命令)呢?簡單來說,我們的程式可能有好多地方要執行同一個功能,拿「複製」來講好了,可能功能表、工具列、右鍵快速功能表、快速鍵都要執行同一個功能,以前傳統視窗寫法就是在物件上點兩下,去編輯事件函數的功能,或許類似物件的事件函數參數相同,但也遇到不同型態的事件函數,這樣就無法共用,變成同樣的動作要寫好多次。

而WPF提供了Command功能,只要在程式中指定好命令名稱和該做的動作之後,任何可以使用Command功能的物件只要在XAML裡面指定Command=”命令名稱”屬性,就可以做到相同的事情了~超簡單啊!!



.net裡面預設有很多已經建立好的Command,譬如ApplicationCommands.Cut就是個「剪下」的Command(注意,這只是個名稱,並沒有實作功能,要實作必須處理Executed的事件),但有時候我們要的功能並沒有提供,像「離開程式」就沒有可對應的Command,這時我們就必須自己製作一個。

目標:按下Ctrl+W快速鍵就能夠關閉程式


方法一:


  1. 在XAML中,<Window.Resources>區段中建立一個RoutedUICommand
    1. <Window.Resources>
    2. <RoutedUICommand x:Key="Quit" Text="離開程式" />
    3. </Window.Resources>

    這樣就建立了一個名為”Quit”的自訂Command定義。
  2. 再來我們要建立快速鍵的指定,在<Window.InputBindings>裡面加入:
    1. <Window.InputBindings>
    2. <KeyBinding Gesture="Ctrl+W" Command="{StaticResource Quit}" />
    3. </Window.InputBindings>

    這樣我們就將Quit的Command與快速鍵Ctrl+W連結在一起了,在任何地方按這個快速鍵就會去執行Quit。
  3. 但現在還沒有任何可執行的功能,所以我們要來指定一下Quit這個Command的實際處理程序。Command總共分CanExecute和Executed這兩個事件,CanExecute回傳是否可執行這個命令,我們可在面做些判斷;而Executed這個事件就是實際去執行該有的動作啦。首先我們先在原始CS檔裡面撰寫好這兩個命令的函數:
    1. /// <summary>
    2. /// Quit命令的實際執行動作
    3. /// </summary>
    4. /// <param name="sender"></param>
    5. /// <param name="args"></param>
    6. void Quit_Executed(object sender, ExecutedRoutedEventArgs args) {
    7. this.Close();
    8. }
    9. /// <summary>
    10. /// 判斷是否能執行Quit命令
    11. /// </summary>
    12. /// <param name="sender"></param>
    13. /// <param name="args"></param>
    14. void Quit_CanExecute(object sender, CanExecuteRoutedEventArgs args) {
    15. args.CanExecute = true; //這裡永遠回傳true,表示永遠都可執行,可自己加入譬如正在跑什麼動作的話就回傳false
    16. }
  4. 接著我們就來綁定這兩個事件,在<Window.CommandBindings>裡面新增一個CommandBinding:
    1. <Window.CommandBindings>
    2. <CommandBinding
    3. Command="{StaticResource Quit}"
    4. CanExecute="Quit_CanExecute"
    5. Executed="Quit_Executed" />
    6. </Window.CommandBindings>
  5. 做到此,我們的程式已經有了快速鍵Ctrl+W離開程式的功能啦~若希望其他物件點下去也能有這功能,只要加入屬性Command=”{StaticResource Quit}”就可以囉~

方法二:

如果你覺得寫Class比較帥,而且可以自己定義命名空間方便管理的話,也可以完全透過程式來達成。
  1. 新增一個Class,也順便指定一下Namespace(這裡假設我的專案叫MyProject)
    1. using System.Windows.Input;
    2. namespace MyProject.MyCommands
    3. {
    4. class SystemCommands
    5. {
    6. /// <summary>
    7. /// 關閉應用程式的自訂Command
    8. /// </summary>
    9. public static RoutedUICommand Quit = new RoutedUICommand("離開應用程式", "QuitCommand", typeof(MainWindow));
    10. }
    11. }
  2. 一樣如方法一的步驟三,先新增兩個事件的處理函數。
  3. 在主XAML的程式碼檔的建構子裡面,增加CommandBinding物件:
    1. CommandBinding cbQuit = new CommandBinding(
    2. MyProject.MyCommands.SystemCommands.Quit,
    3. new ExecutedRoutedEventHandler(Quit_Executed),
    4. new CanExecuteRoutedEventHandler(Quit_CanExecute)
    5. );
    6. //加到CommandBindings裡面
    7. this.CommandBindings.Add(cbQuit);
  4. 再增加InputBinding物件:
    1. InputBinding ibQuit = new InputBinding(
    2. MyProject.MyCommands.SystemCommands.Quit,
    3. new KeyGesture(Key.W, ModifierKeys.Control) //就是Ctrl+W
    4. );
    5. //加到InputBindings裡面
    6. this.InputBindings.Add(ibQuit);
  5. 整個段完成如下:
    1. public MainWindow() {
    2. InitializeComponent();
    3. CommandBinding cbQuit = new CommandBinding(
    4. MyProject.MyCommands.SystemCommands.Quit,
    5. new ExecutedRoutedEventHandler(Quit_Executed),
    6. new CanExecuteRoutedEventHandler(Quit_CanExecute)
    7. );
    8. this.CommandBindings.Add(cbQuit);
    9. InputBinding ibQuit = new InputBinding(
    10. MyProject.MyCommands.SystemCommands.Quit,
    11. new KeyGesture(Key.W, ModifierKeys.Control)
    12. );
    13. this.InputBindings.Add(ibQuit);
    14. }
  6. 回到XAML裡,在頂部元素<Window>裡面原有的xmlns底下加上自訂的命名空間:
    1. xmlns:My="clr-namespace:MyProject.MyCommands"
  7. 這樣有物件要使用該命令的話,只需增加底下屬性即可:
    1. Command="My:SystemCommands.Quit"
這樣就大功告成啦~當然你要把兩個方法結合也是可以的,我的作法就是寫自訂Command的Class,在XAML裡面指定CommandBinds和InputBinds,然後加入自訂的命名空間,這樣設計和程式撰寫對我來說是比較直觀的。

參考資料:
http://msdn.microsoft.com/zh-tw/magazine/cc785480.aspx

http://www.cnblogs.com/gnielee/archive/2010/07/16/wpf-custom-hotkey-command.html