WPF 之事件绑定(八)
一、System.Windows.Interactivity 的使用
对于 Button 等控件,在 MVVM 中我们能通过 Command 绑定解决 Click 事件,具体如下:
<Button Margin="10" Height="50" Content="Clear" Command="{Binding Path=Clear}"></Button>
此时,当我们单击 Clear 按钮时,会执行 “Clear“ 命令。若我们需要传递参数,则使用 CommandParameter,如下所示传递:
<Button Margin="10" Height="50" Content="Clear" Command="{Binding Path=Clear}" CommandParameter="{Binding Path=Student}"></Button>
那当我们使用 Button 的 其他事件,例如MouseMove 事件呢?甚至 TextBox 控件没有 Command 属性, 该如何使用 Command 呢?
这就需要我们通过 Nuget 添加 “System.Windows.Interactivity” 包后,引入如下命名控件:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
例如,我们实现一个 TextBox的 TextChanged事件,当文本内容发生变化,弹出踢提示信息:
<TextBox Height="50" VerticalContentAlignment="Center" Margin="10" BorderBrush="Black" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding DisplayMessage}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
二、带事件参数(EventArgs)的事件绑定
上面介绍的事件绑定并不足以应对所有的情况,因为很多情况下我们还需要从事件的EventArgs中获取数据,例如从MouseMove事件参数中获取鼠标位置和按键状态等。但InvokeCommandAction在未对CommandParameter绑定的情况下给Execute方法传递的参数为null。因此我们需要自己写一个类来处理事件到命令的绑定。自定义 EventCommand 如下所示:
class EventCommand : TriggerAction<DependencyObject>
{
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
// Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommand), new PropertyMetadata(null));
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
// Using a DependencyProperty as the backing store for CommandParameter. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(EventCommand), new PropertyMetadata(null));
protected override void Invoke(object parameter)
{
if (CommandParameter != null)
{
parameter = CommandParameter;
}
Command?.Execute(parameter);
}
}
例如,我们要实现对一个 TextBox 鼠标位置信息的获取,具体绑定如下:
<TextBox Height="150" Margin="10" Background="LightSteelBlue" Text="获取鼠标位置" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseMove">
<local:EventCommand Command="{Binding GetPositionCommand}"></local:EventCommand>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
如此,ViewModel 的绑定命令就可以收到事件参数了:
public ICommand GetPositionCommand { get; set; }
private void GetPositionCommandExecute(object obj)
{
var args = obj as MouseEventArgs;
if (args != null)
{
var pos = args.GetPosition(args.Device.Target);
CurrentPosition = new Position()
{
X = pos.X,
Y = pos.Y,
};
}
}
public WindowVM()
{
_position = new Position();
GetPositionCommand=new RelayCommand(GetPositionCommandExecute, null);
}