前言:在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控件
public RelayCommand<ComboBox> SelectionComboBoxCommand
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一样
public DelegateCommand<ComboBox> SelectionComboBoxCommand2
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.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>();
public ObservableCollection<string> Messages
get { return messages; }
set { messages = value; RaisePropertyChanged("Messages"); }
public RelayCommand ClickCommand
var command = new RelayCommand(() =>
messages.Add($"您单击了[{DateTime.Now}]");
});
return command;
public RelayCommand<Button> ClickWithButtonCommand
var command = new RelayCommand<Button>((button) =>
messages.Add($"您单击了({button.Content})[{DateTime.Now}]");
});
return command;
public RelayCommand<TextBox> GotFocusWithTextBoxCommand
var command = new RelayCommand<TextBox>((textbox) =>
messages.Add($"({textbox.Name})获得焦点[{DateTime.Now}]");
});
return command;
public RelayCommand<TextBox> ChangedTextBoxCommand
var command = new RelayCommand<TextBox>((textbox) =>
messages.Add($"({textbox.Text})[{DateTime.Now}]");
});
return command;
public RelayCommand<ComboBox> SelectionComboBoxCommand
var command = new RelayCommand<ComboBox>((control) =>
var item = control.SelectedItem as ComboBoxItem;
if (item != null)
messages.Add($"({item.Content})[{DateTime.Now}]");
});
return command;
public DelegateCommand<ComboBox> SelectionComboBoxCommand2
var command = new DelegateCommand<ComboBox>((control) =>
var item = control.SelectedItem as ComboBoxItem;
if (item != null)
messages.Add($"({item.Content})[{DateTime.Now}]");
});
return command;
下面为新增自定义控件及控件行为附加示例

附带升级版源码(增加自定义控件中自定义事件的命令绑定和控件行为扩展示例)
作者:WPF中文网
前言:在WPF中,将命令绑定到一个Button的Command属性中是非常简单的事情,例如:<Button Content="单击命令" Command="{Binding ClickCommand}"/>但是很多时候,我们要实现其它事件的命令绑定,以此实现彻底的MVVM开发模式,那就得用到微软另外一个神器了!它就是程序集System.Windows.Interactivity,在网上可以下载System.Windows.Interactivity.dll这个库文件。当然,在mvvmli
wpf中关于按钮Button、菜单项MenuItem等关于点击交互的事件,可以通过命令Command在ViewModel 中实现。将控件属性或者控件本,当做参数传入在CommandParameter中绑定ElementName对应控件的name,和属性名称。
除了点击事件通过Command绑定之外,想要绑定其他命令如MouseEnter、SelectionChanged等事件,则需要导入专门的nuget包,安装System.Windows.Interactivity.WPF包
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Content="+" Command="{Binding ButtonIncrease}" Height="20" Margin="5,-2,0,0"
<Button Content="操作"
Command="{Binding 命令名称}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=SelectedItem}" />
RelativeSource可以将某个控件作为参数转递给Command里面;
它有三个常用属性
//RelativeSou
在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列,并将Button的Command属性绑定到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的外观和行为,并将Button的Command属性绑定到ViewModel中的命令属性。还可以将Button的CommandParameter属性绑定到DataGrid中的当前行,以便在命令方法中访问该行的数据。