<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding DataContext.ImgClickCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"
CommandParameter="{Binding ElementName=gd_img}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
这是调用原有的方法来实现事件命令的绑定,该代码部分把MouseLeftButtonDown事件绑定到了ImgClickCommand命令下,并把gd_img这个Grid传递过去。一般情况下传递一个参数或者不传可以满足大多情况,但针对业务较复杂的需求一个参数的传递已经不足以满足我们的需求。下面提供两个实现方案来解决这一问题。
第一种方式:重写InvokeCommandAction来扩充返回的参数
public class EventToCommand : TriggerAction<DependencyObject>
private string commandName;
public readonly static DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(EventToCommand), null);
public readonly static DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(EventToCommand), new PropertyMetadata(null, (DependencyObject s, DependencyPropertyChangedEventArgs e) =>
EventToCommand sender = s as EventToCommand;
if (sender == null)
return;
if (sender.AssociatedObject == null)
return;
/// <summary>
/// 获取或设置此操作应调用的命令。这是依赖属性。
/// </summary>
/// <value>要执行的命令。</value>
/// <remarks>如果设置了此属性和 CommandName 属性,则此属性将优先于后者。</remarks>
public ICommand Command
return (ICommand)base.GetValue(EventToCommand.CommandProperty);
base.SetValue(EventToCommand.CommandProperty, value);
/// <summary>
/// 获得或设置命令参数。这是依赖属性。
/// </summary>
/// <value>命令参数。</value>
/// <remarks>这是传递给 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks>
public object CommandParameter
return base.GetValue(EventToCommand.CommandParameterProperty);
base.SetValue(EventToCommand.CommandParameterProperty, value);
/// <summary>
/// 获得或设置此操作应调用的命令的名称。
/// </summary>
/// <value>此操作应调用的命令的名称。</value>
/// <remarks>如果设置了此属性和 Command 属性,则此属性将被后者所取代。</remarks>
public string CommandName
base.ReadPreamble();
return this.commandName;
if (this.CommandName != value)
base.WritePreamble();
this.commandName = value;
base.WritePostscript();
/// <summary>
/// 调用操作。
/// </summary>
/// <param name="parameter">操作的参数。如果操作不需要参数,则可以将参数设置为空引用。</param>
protected override void Invoke(object parameter)
if (base.AssociatedObject == null)
return;
ICommand command = this.ResolveCommand();
* ★★★★★★★★★★★★★★★★★★★★★★★★
* 注意这里添加了事件触发源和事件参数
* ★★★★★★★★★★★★★★★★★★★★★★★★
ExCommandParameter exParameter = new ExCommandParameter
Sender = base.AssociatedObject,
//Parameter = GetValue(CommandParameterProperty),
Parameter = this.CommandParameter,
EventArgs = parameter as EventArgs
if (command != null && command.CanExecute(exParameter))
* ★★★★★★★★★★★★★★★★★★★★★★★★
* 注意将扩展的参数传递到Execute方法中
* ★★★★★★★★★★★★★★★★★★★★★★★★
command.Execute(exParameter);
private ICommand ResolveCommand()
if (this.Command != null)
return this.Command;
if (base.AssociatedObject == null)
return null;
ICommand result = null;
Type type = base.AssociatedObject.GetType();
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
for (int i = 0; i < properties.Length; i++)
PropertyInfo propertyInfo = properties[i];
if (typeof(ICommand).IsAssignableFrom(propertyInfo.PropertyType) && string.Equals(propertyInfo.Name, this.CommandName, StringComparison.Ordinal))
result = (ICommand)propertyInfo.GetValue(base.AssociatedObject, null);
break;
return result;
EventToCommand 类是我参考大神的博客【1】以及反编译系统类仿照着来写的,基本变化不大,改动体现在invoke方法里,对返回的参数进行了打包(把数据封装成了类)
public class ExCommandParameter
/// <summary>
/// 事件触发源
/// </summary>
public DependencyObject Sender { get; set; }
/// <summary>
/// 事件参数
/// </summary>
public EventArgs EventArgs { get; set; }
/// <summary>
/// 额外参数
/// </summary>
public object Parameter { get; set; }
ExCommandParameter 类就是我们扩充的数据类
界面上的调用方式为:
首先要引入命名空间,如:
xmlns:loc="clr-namespace:WpfProgect.Base"
然后我们就可以为所欲为的调用了,如下:
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<!--★★★扩展的InvokeCommandAction★★★-->
<loc:EventToCommand Command="{Binding StretchSelectionChangedCommand}"
CommandParameter ="{Binding ElementName=sampleViewBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
后台使用方法:
首先需要在ViewModel里进行命令绑定的初始化,如:
StretchSelectionChangedCommand = new DelegateCommand()
{ ExecuteActionObj = new Action<object>(StretchSelectionChanged) };
当然,具体实现方式要根据自己编写的DelegateCommand类来决定。
绑定的StretchSelectionChanged方法实现如下:
private void StretchSelectionChanged(object obj)
ComboBox cbStretch = ((ExCommandParameter)obj).Sender as ComboBox;
Viewbox sampleViewBox = ((ExCommandParameter)obj).Parameter as Viewbox;
if (cbStretch.SelectedItem != null)
sampleViewBox.Stretch = uiModel.StretchMode;
第二种方式:运用Behavior来实现事件,再运用视图树VisualTree来找所需的父控件或者子控件(控件到手了,就可以取到所需的参数),或者通过写扩展属性的方式来获取控件,以下Demo是通过写扩展属性来实现的。
同样的我们需要引入命名空间来使用我们的SliderBehavior
xaml调用方式如下:
<Slider x:Name="HSlider" Minimum="0" Maximum="100" Height="24" Margin="79,0,91,42" VerticalAlignment="Bottom" Width="150">
<i:Interaction.Behaviors>
<behav:SliderBehavior TargetGrid="{Binding ElementName=theContainer}"
TargetViewBox="{Binding ElementName=sampleViewBox}"/>
</i:Interaction.Behaviors>
</Slider>
SliderBehavior类如下:
class SliderBehavior : Behavior<Slider>
public readonly static DependencyProperty TargetGridProperty = DependencyProperty.Register("TargetGrid", typeof(Grid), typeof(SliderBehavior), null);
public readonly static DependencyProperty TargetViewBoxProperty = DependencyProperty.Register("TargetViewBox", typeof(Viewbox), typeof(SliderBehavior), null);
/// <summary>
/// 获得或设置命令参数。这是依赖属性。
/// </summary>
/// <value>命令参数。</value>
/// <remarks>这是传递给 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks>
public Grid TargetGrid
return (Grid)base.GetValue(SliderBehavior.TargetGridProperty);
base.SetValue(SliderBehavior.TargetGridProperty, value);
public Viewbox TargetViewBox
return (Viewbox)base.GetValue(SliderBehavior.TargetViewBoxProperty);
base.SetValue(SliderBehavior.TargetViewBoxProperty, value);
protected override void OnAttached()
base.OnAttached();
this.AssociatedObject.ValueChanged += new RoutedPropertyChangedEventHandler<double>(HSlider_ValueChanged);
protected override void OnDetaching()
base.OnDetaching();
this.AssociatedObject.ValueChanged -= HSlider_ValueChanged;
void HSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
if (this.AssociatedObject.Name == "HSlider")
TargetViewBox.Width = TargetGrid.ActualWidth * this.AssociatedObject.Value / 100.0;
else TargetViewBox.Height = TargetGrid.ActualHeight * this.AssociatedObject.Value / 100.0;
Ps:看的时候可以忽略事件的实现内容,具体看下实现流程与调用方式。
参考博客:【1】https://blog.csdn.net/qing2005/article/details/6680047
Demo下载地址:https://download.csdn.net/download/iqqqqu/10924283
&lt;i:Interaction.Triggers&gt; &lt;i:EventTrigger EventName="MouseLeftButtonDown"&gt; &lt;i:InvokeCommandAction Command="{Binding DataContext.ImgClickCommand, RelativeSo...
前言:在WPF中,将命令绑定到一个Button的Command属性中是非常简单的事情,例如:
<Button Content="单击命令" Command="{Binding ClickCommand}"/>
但是很多时候,我们要实现其它事件的命令绑定,以此实现彻底的MVVM开发模式,那就得用到微软另外一个神器了!它就是程序集System.Windows.Interactivity,在网上可以下载System.Windows.Interactivity.dll这个库文件。
当然,在mvvmli
我们都知道WPF中的命令在结合MVVM模式的框架使用之后(框架重新实现了ICommand),可以解耦。但并不是所有控件都可以绑定命令的,比如TextBox、ComboBox等。在使用这类控件时,如果你想让它的某个事件激发时调用ViewModel中的方法,往往需要把ViewModel中的方法暴露给View,然后在事件处理器中调用。这种调用方式增加了耦合度,虽然从短期实现来讲也没啥问题,但会让强迫症患者非常难受。目前收集了两种解决方法:这使UIElement类自带的一个属性,
你可以给它添加鼠标按键绑定和键盘
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen
<UserControl
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
</U...