從PRISM開始學WPF(六)MVVM(二)Command-更新至Prism7.1

命令綁定(Command)

[7.1updated]這一節除了基礎app部分,並無什麼變化html

什麼是Command?

先看下微軟官方的說明:c#

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.app

雖然英語捉雞,可是不妨礙咱們閱讀一手資料,燃鵝(●'◡'●),咱們看下Google的翻譯:框架

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

好像也沒什麼用!仍是直接拿例子來看:函數

MainWindow.xamlspa

<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部分:code

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

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 ,就是一個返回布爾型的方法CanExecute來獲取command的可執行狀態,當上面通知他可執行狀態變動後,他就會從新調用CanExecute方法來獲取目前的可執行狀態(也就是按鈕的可按下狀態),來看下這個方法:

private bool CanExecute()
{
     return IsEnabled;
}

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

固然可執行狀態,還有其餘的更優雅的寫法,也就不用寫ExecuteDelegateCommand.RaiseCanExecuteChanged();了,具體代碼以下:

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接口的。
有興趣的能夠看一下淺談WPF中的MVVM框架--MVVMFoundation
可是,做爲高級的咱們,就用高級的封裝,有了火柴誰還燧木取火,233333

複合型命令綁定

一般狀況下,咱們的命令調用者直接調用咱們的命令,可是有些時候,咱們須要從外部(好比其餘的視圖或父視圖)的控件調用該命令,那麼就須要一個CompositeCommand

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

相關文章
相關標籤/搜索