1. 程式人生 > >WPF學習(9)-命令

WPF學習(9)-命令

      有了事件之後,為什麼還需要命令呢?這個問題困擾了很久,直到我研究了設計模式裡面的命令模式。

      命令模式,就是把命令(或者說是控制邏輯抽象成一個物件),然後拆分出命令(Commadn),接收者(Recevicer),呼叫者(Invoker),具體命令(concretecommand),這樣的好處就是降低了耦合,讓程式變得更靈活,也就是設計模式的一個原則,對修改關閉,對擴充套件開放,當然對於大部分小專案來說,沒有持續的升級迭代的,想改隨意改,設計模式也沒有什麼用,,但是以我的經驗,真的是非常有用。

       回到WPF的命令中來,我們可以把他看作是WPF為我們具體實現了命令模式,給我們提供的語法糖,讓我們可以更加快速地實現命令模式。

       比如,我們一個頁面上有好幾個按鈕,按鈕1,按鈕2,按鈕3,按鈕4,按鈕5,如果按鈕1對應幹某件事情,這個事情沒幹完之前,按鈕2,3,4,5的狀態要是不可用,按鈕2對應的事情1,3,4,5不可用,其他類似,那麼我們當然可以在按鈕對應的事件裡面去修改button的狀態,但是這樣有個問題,就是如果按鈕或者別的控制元件有很多,那麼就很麻煩,這個時候我們可以把控制元件的狀態和命令的狀態保持同步,這樣,幾乎看不到後臺有操作前臺狀態的程式碼,非常清晰。

        WPF中的命令,主要記住以下三個東西就行了(暫時)。

        Void Excute(object parameter),這個方法包含應用程式的邏輯處理,就是具體要乾的事情。

        Bool canexcute(object parameter),這個方法就是告訴程式命令的當前狀態,如果可用就是True,反之則為False。

        Canexcutechange事件,當命令狀態發生改變時,引發這個事件,對於使用命令的控制元件,這是指示訊號,表示應該呼叫canexcute方法檢查命令的狀態。通過這個事件,當命令可用時,命令源可啟動自身,當命令不可用時,禁用自身。

        首先我們實現一個內建的命令,最簡單的

        <Button Command="New" Content="Button" HorizontalAlignment="Left" Margin="148,136,0,0" VerticalAlignment="Top" Width="75"/>
         按鈕註冊了一個New的命令,我們發現,按鈕的狀態自動變成灰色了,沒有反應了,因為沒有給命令具體實現

    <Window.CommandBindings>
        <CommandBinding Command="New" Executed="CommandBinding_Executed">           
        </CommandBinding>
    </Window.CommandBindings>

          寫了一個Excuted事件的處理函式,這個時候就變得可用了,接下來,就是如果禁用命令。

           

    <Grid>
        <Button Command="New" Content="Button" HorizontalAlignment="Left" Margin="171,106,0,0" VerticalAlignment="Top" Width="75"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="171,174,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    </Grid>

      現在來用其中一個按鈕的狀態來控制另外一個按鈕對應的命令的可以狀態。

  bool setCanExcute;
   private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = setCanExcute;
        }
    private void Button_Click(object sender, RoutedEventArgs e)
        {
            setCanExcute = true;
        }

     很清晰就可以修改命令的狀態了。

      最後就是自定義命令,然後在應用程式執行過程中去呼叫,這個特別適合,我們封裝好一個命令,然後在程式的N個地方呼叫,比如列印功能,應用程式正在列印的時候,又來了一個命令,那就不要執行了。

      

    public class Class1
    {
        private static RoutedUICommand requery;
        static Class1()
        {
            InputGestureCollection inputs = new InputGestureCollection();
            inputs.Add(new KeyGesture(Key.R, ModifierKeys.Control, "Ctrl+R"));
            requery = new RoutedUICommand("Requery", "Requery", typeof(Class1), inputs);
        }
        public static RoutedUICommand Requery
        {
            get { return requery; }
        }
    }

       上面的程式碼就是定義了一個包含命令的類,包含一個靜態屬性,一個靜態建構函式,和一個欄位。
        使用也很簡單

        

    <Window.CommandBindings>
        <CommandBinding Command="my:Class1.requery" Executed="CommandBinding_Executed">           
        </CommandBinding>
    </Window.CommandBindings>

    把這個命令作為窗體的命令繫結進去,然後直接呼叫就行啦。

     當然對於還有一些應用,是動態生成的控制元件,就需要使用程式碼去做命令繫結,邏輯是一樣的,就是用程式碼實現。