关于WPF中Command绑定传参数以及将命令绑定到其它事件的方法

前言:在WPF中,将命令绑定到一个Button的Command属性中是非常简单的事情,例如:

<Button Content="单击命令" Command="{Binding ClickCommand}"/>

但是很多时候,我们要实现其它事件的命令绑定,以此实现彻底的MVVM开发模式,那就得用到微软另外一个神器了!它就是程序集System.Windows.Interactivity,在网上可以下载System.Windows.Interactivity.dll这个库文件。

当然,在mvvmlight中,已经集成了这个库文件,所以我们新建一个WPF项目后,通过“管理Nuget程序包"下载安装mvvmlight到项目中后,就可以直接使用了,mvvmlight组件是WPF常见开发包,它提供了一个GalaSoft.MvvmLight.Command命令空间,其中有RelayCommand和RelayCommand<T>两个类扩展了ICommand接口,特别是RelayCommand<T>类,它能实现参数传递。

比如我们有一个ComboBox控件,当用户在UI端选定某个子项后,要将选定的值传入到ViewModel中,这里就需要将ComboBox的SelectionChanged事件绑定到一个命令(SelectionComboBoxCommand),绑定的同时可将当前这个ComboBox控件作为参数传递给SelectionComboBoxCommand命令,这样就可以在ViewModel中去作处理了,那么具体的操作怎么实现呢?

首先是前端代码:

<ComboBox>
  <i:Interaction.Triggers>
      <i:EventTrigger EventName="SelectionChanged">
          <i:InvokeCommandAction Command="{Binding SelectionComboBoxCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}}"/>
      </i:EventTrigger>
  </i:Interaction.Triggers>
  <ComboBoxItem Content="张三"/>
  <ComboBoxItem Content="李四"/>
  <ComboBoxItem Content="王五"/>
</ComboBox>

这里就使用了System.Windows.Interactivity这个空间的Interaction.Triggers,将ComboBox的SelectionChanged事件传递到SelectionComboBoxCommand命令中,在后端,SelectionComboBoxCommand定义成泛型,接收前端传入的ComboBox控件

/// <summary>
/// 获取ComboBox的选定项
/// </summary>
public RelayCommand<ComboBox> SelectionComboBoxCommand
{
    get
    {
        var command = new RelayCommand<ComboBox>((control) =>
        {
            var item = control.SelectedItem as ComboBoxItem;
            if (item != null)
                messages.Add($"({item.Content})[{DateTime.Now}]");
        });
        return command;
    }
}

如此,就可以拿到ComboBox的SelectedItem ,并进行相应的处理了。本例中还展示了Microsoft.Practices.Prism空间中的DelegateCommand类的用法,和mvvmlight中的RelayCommand一样

/// <summary>
/// 获取ComboBox的选定项
/// </summary>
public DelegateCommand<ComboBox> SelectionComboBoxCommand2
{
    get
    {
        var command = new DelegateCommand<ComboBox>((control) =>
        {
            var item = control.SelectedItem as ComboBoxItem;
            if (item != null)
                messages.Add($"({item.Content})[{DateTime.Now}]");
        });
        return command;
    }
}

完整的代码如下:

前端代码

<Window x:Class="WpfCommands.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfCommands" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        mc:Ignorable="d" DataContext="{Binding Source={StaticResource Locator},Path=Main}"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <StackPanel>
            <Button Content="单击命令" Command="{Binding ClickCommand}"/>
            <Button Content="单击命令带参数" Command="{Binding ClickWithButtonCommand}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
            <TextBox>
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="GotFocus">
                        <i:InvokeCommandAction Command="{Binding GotFocusWithTextBoxCommand }" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=TextBox}}"/>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="TextChanged">
                        <i:InvokeCommandAction Command="{Binding ChangedTextBoxCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=TextBox}}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
            <ComboBox>
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <i:InvokeCommandAction Command="{Binding SelectionComboBoxCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
                <ComboBoxItem Content="张三"/>
                <ComboBoxItem Content="李四"/>
                <ComboBoxItem Content="王五"/>
            </ComboBox>
        </StackPanel>
        <ListBox Grid.Column="1" ItemsSource="{Binding Messages}"/>
    </Grid>
</Window>

ViewModel代码

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace WpfCommands.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {

        }

        private ObservableCollection<string> messages = new ObservableCollection<string>();
        /// <summary>
        /// 运行提示
        /// </summary>
        public ObservableCollection<string> Messages
        {
            get { return messages; }
            set { messages = value; RaisePropertyChanged("Messages"); }
        }

        /// <summary>
        /// 单击命令
        /// </summary>
        public RelayCommand ClickCommand
        {
            get
            {
                var command = new RelayCommand(() =>
                {
                    messages.Add($"您单击了[{DateTime.Now}]");
                });
                return command;
            }
        }

        /// <summary>
        /// 单击命令带参数
        /// </summary>
        public RelayCommand<Button> ClickWithButtonCommand
        {
            get
            {
                var command = new RelayCommand<Button>((button) =>
                {
                    messages.Add($"您单击了({button.Content})[{DateTime.Now}]");
                });
                return command;
            }
        }

        /// <summary>
        /// TextBox获得焦点
        /// </summary>
        public RelayCommand<TextBox> GotFocusWithTextBoxCommand
        {
            get
            {
                var command = new RelayCommand<TextBox>((textbox) =>
                {
                    messages.Add($"({textbox.Name})获得焦点[{DateTime.Now}]");
                });
                return command;
            }
        }

        /// <summary>
        /// TextBox内容被修改
        /// </summary>
        public RelayCommand<TextBox> ChangedTextBoxCommand
        {
            get
            {
                var command = new RelayCommand<TextBox>((textbox) =>
                {
                    messages.Add($"({textbox.Text})[{DateTime.Now}]");
                });
                return command;
            }
        }

        /// <summary>
        /// 获取ComboBox的选定项
        /// </summary>
        public RelayCommand<ComboBox> SelectionComboBoxCommand
        {
            get
            {
                var command = new RelayCommand<ComboBox>((control) =>
                {
                    var item = control.SelectedItem as ComboBoxItem;
                    if (item != null)
                        messages.Add($"({item.Content})[{DateTime.Now}]");
                });
                return command;
            }
        }


        /// <summary>
        /// 获取ComboBox的选定项
        /// </summary>
        public DelegateCommand<ComboBox> SelectionComboBoxCommand2
        {
            get
            {
                var command = new DelegateCommand<ComboBox>((control) =>
                {
                    var item = control.SelectedItem as ComboBoxItem;
                    if (item != null)
                        messages.Add($"({item.Content})[{DateTime.Now}]");
                });
                return command;
            }
        }

    }
}

在这里插入图片描述
源码下载

下面为新增自定义控件及控件行为附加示例
在这里插入图片描述

附带升级版源码(增加自定义控件中自定义事件的命令绑定和控件行为扩展示例)

作者:WPF中文网

  • 10
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
WPF MVVM,你可以使用命令模式来将一个按钮的点击事件绑定到ViewModel的一个方法。以下是在DataGrid使用按钮并绑定命令方法的步骤: 1. 在ViewModel创建一个ICommand属性,该属性将绑定到按钮的Command属性。可以使用RelayCommand等现有的ICommand实现,也可以自己实现ICommand接口。如下所示: ```csharp public class MyViewModel { public ICommand MyCommand { get; set; } public MyViewModel() { MyCommand = new RelayCommand(ExecuteMyCommand); } private void ExecuteMyCommand(object parameter) { // 在这里编写命令方法的代码 } } ``` 2. 在XAML,在DataGrid创建一个Button列,并将ButtonCommand属性绑定到ViewModel命令属性。如下所示: ```xaml <DataGrid ...> <DataGrid.Columns> ... <DataGridTemplateColumn Header="Action"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Content="Do Something" Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" CommandParameter="{Binding}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> ``` 注意,这里使用了RelativeSource来绑定到Window的DataContext,因为DataGrid的DataContext通常是绑定到ViewModel的。 3. 运行应用程序并单击按钮时,将调用ViewModel的ExecuteMyCommand方法。 请注意,如果你要在DataGrid使用按钮,可能需要使用DataGridTemplateColumn来创建一个自定义列。在该列,使用DataTemplate来定义Button的外观和行为,并将ButtonCommand属性绑定到ViewModel命令属性。还可以将ButtonCommandParameter属性绑定到DataGrid的当前行,以便在命令方法访问该行的据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值