从 PRISM 开始学 WPF(一)WPF? http://www.cnblogs.com/hicolin/p/8694714.html
从 PRISM 开始学 WPF(二)Prism? http://www.cnblogs.com/hicolin/p/8694828.html
从 PRISM 开始学 WPF(三)Prism-Region? http://www.cnblogs.com/hicolin/p/8694861.html
从 PRISM 开始学 WPF(四)Prism-Module? http://www.cnblogs.com/hicolin/p/8694892.html
从 PRISM 开始学 WPF(五)MVVM(一)ViewModel? http://www.cnblogs.com/hicolin/p/8694920.html
从 PRISM 开始学 WPF(六)MVVM(二)Command? http://www.cnblogs.com/hicolin/p/8694940.html
从 PRISM 开始学 WPF(七)MVVM(三)事件聚合器 EventAggregator? http://www.cnblogs.com/hicolin/p/8707903.html
命令绑定(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 是一个由多个子命令组成的命令. 它提供了执行子命令的所有关联方法 (Execute 和 CanExecute) 的功能, 当所有子命令的可执行状态为 True 的时候 CompositeCommand 才可以被执行.
看下具体应用的代码:
声明:
public CompositeCommand SaveCommand { get; } = new CompositeCommand();
注册子命令:
SaveCommand.RegisterCommand(UpdateCommand);
取消注册:
SaveCommand.UnregisterCommand(UpdateCommand);
来源: http://www.bubuko.com/infodetail-2629957.html