上文中对命令的使用都是直接通过控件中的Command
属性来进行绑定的,默认情况下,Command
属性所绑定的命令,其触发条件是鼠标的点击。
接下来学习如何使用其他行为来作为命令的触发条件。
LeftClick
:单击鼠标左键。
LeftDoubleClick
:双击鼠标左键。
MiddleClick
:单击鼠标中键。
MiddleDoubleClick
:双击鼠标中键。
RightClick
:单击鼠标右键。
RightDoubleClick
:双击鼠标右键。
None
:不执行任何操作。
WheelClick
:旋转鼠标滚轮。
要将鼠标的其他行为来作为命令的触发条件,需要使用控件的InputBindings
属性,并在其中添加MouseBinding
对象。
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" Executed="Button_Executed" CanExecute="Button_CanExecute"/>
</Window.CommandBindings>
<Grid>
<StackPanel>
<Button Content="MouseDoubleClick">
<Button.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick"
Command="ApplicationCommands.Open"/>
</Button.InputBindings>
</Button>
</StackPanel>
</Grid>
要将键盘的行为作为命令的触发条件,需要使用控件的InputBindings
属性,并在其中添加KeyBinding
对象。
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" Executed="Button_Executed" CanExecute="Button_CanExecute"/>
</Window.CommandBindings>
<Grid>
<StackPanel>
<Button Content="Alt+K">
<Button.InputBindings>
<KeyBinding Key="K" Modifiers="Alt"
Command="ApplicationCommands.Open"/>
</Button.InputBindings>
</Button>
</StackPanel>
</Grid>
用的时候发现,如果控件对象是个按钮,要先点击一下按钮,将焦点聚焦到按钮上,按键盘才有用。可能还有其他解决方案,基本上用不上,暂时不研究了。
进行任意事件的绑定处理前,先通过Nuget安装Microsoft.Xaml.Behaviors.Wpf
库。
Command层
public class MyCommand : ICommand
{
//这里为了方便就不去调用检查事件了
public event EventHandler CanExecuteChanged;
public Func<object,bool> DoCanExecute{ get; set; }
public bool CanExecute(object parameter)
{
return DoCanExecute(parameter) == true;
}
public Action<object> DoExecute { get; set; }
public void Execute(object parameter)
{
DoExecute(parameter);
}
}
Model层
public class MainModel
{
public MyCommand MyCommand { get; set; }
public MainModel()
{
MyCommand = new MyCommand
{
DoExecute = DoExecute,
DoCanExecute = DoCanExecute
};
}
private void DoExecute(object obj)
{
Debug.WriteLine("执行命令");
}
private bool DoCanExecute(object obj)
{
Debug.WriteLine("判断是否可执行命令");
return true;
}
}
ViewModel层
public class MainViewModel
{
public MainModel MainModel { get; set; } = new MainModel();
}
XAML
<Window ......
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
......>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<ComboBox>
<!--进行命令绑定-->
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding MainModel.MyCommand}" CommandParameter="123"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBoxItem Content="AAA"/>
<ComboBoxItem Content="BBB"/>
<ComboBoxItem Content="CCC"/>
</ComboBox>
</StackPanel>
</Grid>
</Window>
如果希望在触发命令时,将事件的参数传递过去,可以设置属性PassEventArgsToCommand="True"
,例如<i:InvokeCommandAction Command="{Binding MainModel.MyCommand}" PassEventArgsToCommand="True"/>
,如果PassEventArgsToCommand
与CommandParameter
同时存在,优先使用CommandParameter
。
尽管可以传递事件的参数,但是却无法像原生的事件方法那样将触发事件的控件对象也一起传递回去,如果需要达到这样的效果,可以考虑直接绑定到方法上(下文中的方法)。
除了绑定命令对象外,还可以直接绑定到方法上,其方法签名中的参数列表与原生的事件处理方法的相同。
ViewModel层
关于对应函数的签名,可以通过控件的对应事件处理函数自动生成后复制出来
public class MainViewModel
{
......
public void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//这里可以获取到控件对象,进行业务处理
}
.....
}
XAML
<Window ......
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
......>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<ComboBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:CallMethodAction TargetObject="{Binding}" MethodName="ComboBox_SelectionChanged"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBoxItem Content="AAA"/>
<ComboBoxItem Content="BBB"/>
<ComboBoxItem Content="CCC"/>
</ComboBox>
</Grid>
</Window>
可以同时使用绑定命令和绑定方法。
XAML
<Window ......
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
......>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<ComboBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:CallMethodAction TargetObject="{Binding}" MethodName="ComboBox_SelectionChanged"/>
<i:InvokeCommandAction Command="{Binding MainModel.MyCommand}" CommandParameter="123"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBoxItem Content="AAA"/>
<ComboBoxItem Content="BBB"/>
<ComboBoxItem Content="CCC"/>
</ComboBox>
</Grid>
</Window>