从PRISM开始学WPF(六)MVVM(二)Command?

原文:从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);

原文地址:https://www.cnblogs.com/lonelyxmas/p/9131408.html

时间: 2024-07-31 07:23:30

从PRISM开始学WPF(六)MVVM(二)Command?的相关文章

从PRISM开始学WPF(六)MVVM(三)事件聚合器EventAggregator?

从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? Event aggregation. For communication acros

从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator?

原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator? 从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(三)事件聚合器EventAggrega

从PRISM开始学WPF(二)Prism?

原文:从PRISM开始学WPF(二)Prism? 目录: 从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? 0x1 PRISM? PR

从PRISM开始学WPF(四)Prism-Module?

原文:从PRISM开始学WPF(四)Prism-Module? 从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? 0x4Modules

从PRISM开始学WPF(一)WPF?

原文:从PRISM开始学WPF(一)WPF? 我最近打算学习WPF ,在寻找MVVM框架的时候发现了PRISM,在此之前还从一些博客上了解了其他的MVVM框架,比如浅谈WPF中的MVVM框架--MVVMFoundation 中提到的MVVMFoundation,再比如 ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet 中的Stylet.在知道PRISM是微软自家的框架的时候,就毫不犹豫的选了他,即便个人很倾向于可爱的Stylet.作为初学者,对WPF都没有很好的了解的情

从PRISM开始学WPF(九)交互Interaction?

原文:从PRISM开始学WPF(九)交互Interaction? 0x07交互 这是这个系列的最后一篇了,主要介绍了Prism中为我们提供几种弹窗交互的方式. Notification通知式 Prism通过InteractionRequest 来实现弹窗交互,它是一个泛型接口,不同的类型对应不同类型的弹窗方式. 在使用InteractionRequest的时候需要在,xaml中需要注册一个Trigger: <i:Interaction.Triggers> <prism:Interacti

从PRISM开始学WPF(八)导航Navigation?

原文:从PRISM开始学WPF(八)导航Navigation? 0x6Navigation Basic Navigation Prism中的Navigation提供了一种类似导航的功能,他可以根据用户的输入,来刷新UI. 先看一个最简单的例子,通过按钮来导航到一个视图,在这里,视图被注册为Navication. public void Initialize() { _container.RegisterTypeForNavigation<ViewA>(); _container.Registe

WPF之MVVM(Step4)&mdash;&mdash;使用Prism(2)

上一篇简单介绍使用Prism中的NotificationObject,以及DelegateCommand.这一篇更是简单,仅仅描述下DelegateCommand<T>如何使用. ICommand接口一开始提供的就是带参数的方法,而我们使用时经常会遇到那个参数毫无用处的情况,Prism也就帮了偶们一把啦.当然,Prism并没有忘记我们有时还是要参数滴.   在定义上,我们使用ICommand定义,DelegateCommand和DelegateCommand<T>一样.在实例化时有

应该是写点儿东西的时候了 -- 基于WPF和MVVM的项目开发 -- 前言

自从来了Sibet就一直在做项目,刚开始的时候是个半成品的体外诊断设备应用软件,关于血栓的弹力图谱绘制和信息管理.原来的软件是外包的,但由于我方没有给后续的经费(如何跟外包公司谈合同尚未经历过)导致乙方做了一半就不愿意再等了,毕竟搭软件的速度还是比硬件的迭代周期要快不少.原版本基于.net 3.5的WinForm开发,类似于很多年前做过的网站项目,代码看起来不吃力,但由于项目的进展软件也要随之做优化和扩展,而原有的MVC软件框架扩展起来实在很麻烦,这时候才发现把逻辑和界面写在一起弊端多多啊.好在