添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
纯真的哑铃  ·  如何防止 ComboBox 中的 ...·  1 月前    · 
一身肌肉的杯子  ·  C#MVVM ...·  1 月前    · 
有腹肌的生菜  ·  WPFMVVM ...·  1 月前    · 
忧郁的大象  ·  Frequency - Key Stage ...·  3 月前    · 
咆哮的创口贴  ·  MySQLdb.ProgrammingErr ...·  4 月前    · 
谦逊的佛珠  ·  heavy bread ...·  4 月前    · 
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议 》和 《 阿里云开发者社区知识产权保护指引 》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单 进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

从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; }
                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);
    原文:WPF Navigation 在开始学习WPF时,一开始对WPF的Window, Page, UserControl感到很迷惑。不知道什么时候该使用哪一个。下面简单介绍一下这三者的区别。 Window:故名思意,桌面程序的窗体。
    原文:(WPF, MVVM) Event 处理 WPF的有些UI元素有Command属性可以直接实现绑定,如Button 但是很多Event的触发如何绑定到ViewModel中的Command呢? 答案就是使用EventTrigger可以实现。
    从PRISM开始学WPF(四)Prism-Module? 从PRISM开始学WPF(五)MVVM(一)ViewModel? 从PRISM开始学WPF(六)MVVM(二)Command? 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator? 0x5 MVVM 蛤蛤,终于到MVVM了。