1. 程式人生 > >從PRISM開始學WPF(六)MVVM(二)Command?

從PRISM開始學WPF(六)MVVM(二)Command?

方法 應用 anti cde action rop check schema .html

原文:從PRISM開始學WPF(六)MVVM(二)Command?

從PRISM開始學WPF(一)WPF?

從PRISM開始學WPF(二)Prism?

從PRISM開始學WPF(三)Prism-Region?

從PRISM開始學WPF(四)Prism-Module?

從PRISM開始學WPF(五)MVVM(一)ViewModel?

從PRISM開始學WPF(六)MVVM(二)Command?

從PRISM開始學WPF(七)MVVM(三)事件聚合器EventAggregator?

命令綁定(Command)

什麽是Command?

先看下微軟官方的說明:

Commanding is an input mechanism in Windows Presentation Foundation (WPF) which provides input handling at a more semantic level than device input. Examples of commands are the Copy

, Cut, and Paste operations found on many applications.

雖然英語捉雞,但是不妨礙我們閱讀一手資料,燃鵝(●‘?‘●),我們看下Google的翻譯:

指令是Windows Presentation Foundation(WPF)中的一種輸入機制,它提供比設備輸入更多語義級別的輸入處理。命令的例子是在許多應用程序中找到的復制剪切粘貼操作。

好像也沒什麽用!還是直接拿例子來看:

MainWindow.xaml

<Window x:Class="UsingDelegateCommands.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="Using DelegateCommand" Width="350" Height="275">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <CheckBox IsChecked="{Binding IsEnabled}" Content="Can Execute Command" Margin="10"/>
        <Button Command="{Binding ExecuteDelegateCommand}" Content="DelegateCommand" Margin="10"/>
        <Button Command="{Binding DelegateCommandObservesProperty}" Content="DelegateCommand ObservesProperty" Margin="10"/>
        <Button Command="{Binding DelegateCommandObservesCanExecute}" Content="DelegateCommand ObservesCanExecute" Margin="10"/>
        <Button Command="{Binding ExecuteGenericDelegateCommand}" CommandParameter="Passed Parameter" Content="DelegateCommand Generic" Margin="10"/>
        <TextBlock Text="{Binding UpdateText}" Margin="10" FontSize="22"/>
    </StackPanel>
</Window>

MainWindowViewModel.cs

using System;
using Prism.Commands;
using Prism.Mvvm;

namespace UsingDelegateCommands.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                SetProperty(ref _isEnabled, value);
                ExecuteDelegateCommand.RaiseCanExecuteChanged();
            }
        }

        private string _updateText;
        public string UpdateText
        {
            get { return _updateText; }
            set { SetProperty(ref _updateText, value); }
        }

        public DelegateCommand ExecuteDelegateCommand { get; private set; }

        public DelegateCommand<string> ExecuteGenericDelegateCommand { get; private set; }

        public DelegateCommand DelegateCommandObservesProperty { get; private set; }

        public DelegateCommand DelegateCommandObservesCanExecute { get; private set; }


        public MainWindowViewModel()
        {
            ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);

            DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute)
                .ObservesProperty(() => IsEnabled);

            DelegateCommandObservesCanExecute = new DelegateCommand(Execute)
                .ObservesCanExecute(() => IsEnabled);

            ExecuteGenericDelegateCommand = new DelegateCommand<string>(ExecuteGeneric)
                .ObservesCanExecute(() => IsEnabled);
        }

        private void Execute()
        {
            UpdateText = $"Updated: {DateTime.Now}";
        }

        private void ExecuteGeneric(string parameter)
        {
            UpdateText = parameter;
        }

        private bool CanExecute()
        {
            return IsEnabled;
        }
    }
}

View部分:

頭部引入命名空間,指定ViewModeLocator模式:

xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"

接著是一個:

    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    </StackPanel>

接著內部是一組控件,一個CheckBox四個Button一個 TextBlock。

  • CheckBox IsChecked="{Binding IsEnabled}"

復選框的勾選狀態綁定到一個布爾型屬性上。

  • Button Command="{Binding ExecuteDelegateCommand}"

普通命令綁定

  • Button Command="{Binding ExecuteGenericDelegateCommand}" CommandParameter="Passed Parameter"

帶參數的 命令綁定

  • TextBlock Text="{Binding UpdateText}"

為TextBlock的Text屬性綁定數據源

Tips

Binding語法 Property="{Binding PropertyPath}",PropertyPath就是VM

當為Command進行Binding的時候,還可以帶參數,使用CommandParameter屬性,上面的CommandParameter指定了一個字符串“Passed Parameter”,當然還可以為其Binding一個對象。

ViewModel部分:

set方法中的:

SetProperty(ref _isEnabled, value);

屬性變更的通知,當視圖狀態更新後,會通知VM更改_isEnabled

ExecuteDelegateCommand.RaiseCanExecuteChanged();

這段代碼,則會通知ExecuteDelegateCommand的可執行狀態更改了,讓他重新獲取下可執行狀態,那他是怎麽獲取可執行狀態的呢?我們看下這個Command:

ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);

new 的時候,有兩個參數,第一個是Action(無返回類型的方法)Execute,第二個是一個Func

private bool CanExecute()
{
     return IsEnabled;
}

很簡單,直接返回了IsEnabled,而他是跟視圖的CheckBox的IsChecked綁定的,當然也可以返回_isEnabled,而我更傾向後面這個,Public那個是給外人用的,蛤蛤。

當然可執行狀態,還有其他的更優雅的寫法:

            DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute)
                .ObservesProperty(() => IsEnabled);

            DelegateCommandObservesCanExecute = new DelegateCommand(Execute)
                .ObservesCanExecute(() => IsEnabled);

下面這個是帶參數的命令(command),他的回調函數需要一個string類型的參數,在new的時候要指定入參類型:

            ExecuteGenericDelegateCommand = new DelegateCommand<string>(ExecuteGeneric)
                .ObservesCanExecute(() => IsEnabled);

回調函數ExecuteGeneric:

        private void ExecuteGeneric(string parameter)
        {
            UpdateText = parameter;
        }

總結:

ViewModel(簡稱VM,下文也偶爾會出現VM,也指ViewModel)的類需要繼承BindableBase,BindableBase實現了INotifyPropertyChanged接口。

命令類型是DelegateCommand,這繼承自DelegateCommandBase,而DelegateCommandBase實現了ICommand接口。

這倆接口是MVVM的底層接口。有興趣的可以看一下 MVVMFoundation,他封裝沒有那麽多次,只有四個cs文件,可以直接看到,他是如何運用ICommand和INotifyPropertyChanged接口的。

但是,作為高級的我們,就用高級的封裝,有了火柴誰還燧木取火,233333

復合型命令綁定

通常情況下,我們的命令調用者直接調用我們的命令,但是有些時候,我們需要從外部(比如其他的視圖或父視圖)的控件調用該命令,那麽就需要一個CompositeCommand

CompositeCommand是一個由多個子命令組成的命令。它提供了執行子命令的所有關聯方法(ExecuteCanExecute)的功能,當所有子命令的可執行狀態為True的時候CompositeCommand才可以被執行。

看下具體應用的代碼:

聲明:

public CompositeCommand SaveCommand { get; } = new CompositeCommand();

註冊子命令:

SaveCommand.RegisterCommand(UpdateCommand);

取消註冊:

SaveCommand.UnregisterCommand(UpdateCommand);

從PRISM開始學WPF(六)MVVM(二)Command?