命令
数据和界面的交互离不开命令,命令离不开事件,一切的跳转一切的数据交换,皆来源于观察者
系统命令
System.Windows.Input.ICommand 连接数据与界面的桥梁
System.Windows.Input.RoutedCommand 原始桥梁
System.Windows.Input.RoutedUICommand 原始桥梁
ICommandSource InputBinding CommandBinding
自定义命令
public class RelayCommand : ICommand
{
private readonly Action<object> _CanExecute;
private readonly Action _Execute;
public RelayCommand(Action execute)
{
_Execute = execute;
}
public RelayCommand(Action<object> execute)
{
_CanExecute = execute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
// 1.先判断命令是否可以执行(true)
public bool CanExecute(object parameter)
{
return _CanExecute == null ? (_Execute == null ? false : true) : true;
}
// 2.若可以执行,则执行此方法,反之则跳过此方法
public void Execute(object parameter)
{
if (parameter == null)
_Execute?.Invoke();
else
_CanExecute?.Invoke(parameter);
}
}
触发器
NuGet Package
: Microsoft.Xaml.Behaviors.Wpf
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
<RadioButton
Height="60"
Content="{Binding TaskItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"
GroupName="ctl"
IsChecked="{Binding IsTab, Mode=TwoWay}"
Style="{StaticResource MahApps.Styles.RadioButton.Flat}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding DataContext.CheckedCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}, AncestorLevel=1}}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
<Button Command="{Binding AddCmd}" Content="test" />
<TextBlock
Height="50"
HorizontalAlignment="Stretch"
Text="text">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding MouseDownCmd}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
快捷键命令
<Window.InputBindings>
<KeyBinding
Key="T"
Command="{Binding AltCmd}"
Modifiers="Alt" />
</Window.InputBindings>
<Window.Resources>
<RoutedUICommand x:Key="Cut" Text="剪切" />
</Window.Resources>
<Window.CommandBindings>
<CommandBinding
CanExecute="CommandBinding_CanExecute"
Command="{StaticResource Cut}"
Executed="CommandBinding_Cut" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="{StaticResource Cut}" Gesture="Ctrl+X" />
</Window.InputBindings>
private void CommandBinding_Cut(object sender, ExecutedRoutedEventArgs e)
{
vm?.CutCmd.Execute(e.Parameter);
}
//可省略此方法
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
GalaMVVMlight
应用场景
基于自定义命令,分别在触发器和普通命令中的使用
# 空参数
private RelayCommand addCmd;
public RelayCommand AddCmd
{
get
{
return addCmd ?? (addCmd = new RelayCommand(() =>
{
}));
}
}
// 带参数
private RelayCommand checkedCmd;
public RelayCommand CheckedCmd
{
get
{
return checkedCmd ?? (checkedCmd = new RelayCommand(args =>
{
var node = args as TaskModel;
}));
}
}
//快捷键命令
private RelayCommand altCmd;
public RelayCommand AltCmd
{
get
{
return altCmd ?? (altCmd = new RelayCommand(() =>
{
System.Diagnostics.Debug.WriteLine("");
}));
}
}
//Cut
private RelayCommand cutCmd;
public RelayCommand CutCmd
{
get
{
return cutCmd ?? (cutCmd = new RelayCommand(() =>
{
System.Diagnostics.Debug.WriteLine("");
}));
}
}
过去面试中也会被问到此问题,还继续被问道 PreviewMouse 和 Mouse 的区别,隧道和冒泡
隧道 window -> top
冒泡 top -> window