1. 基本知識
微軟預定義了5類100多個常用命令:
ApplicationCommands, NavigationCommands, MediaCommands, EditingCommands and ComponentCommands.
命令的好處:
1).一處定義,到處使用(menu item, toolbar, shortcut)
2).自動監聽快捷鍵
3).根據條件自動更新UI(enable/disable)
命令綁定:
Commands本身什麼也不做,它底層由ICommand組成,包含兩個方法(Execute/CanExecute)一個事件(CanExecuteChanged).要執行實際的action,需要將command和你的代碼關聯起來,這就是Command bindings.
可以像事件一樣理解command,有人觸發command,有人處理command:
1)Command binding決定用哪個command要被觸發;
2)框架負責觸發(執行)command;
3)command具體做什麼,由我們的代碼決定.
The RoutedCommand in WPF is similar to RoutedEvents. The caller raises (executes) the command and the command routes up in the WPF Visual Tree until a CommandBinding handles the command. You can stop the route by setting the e.Handled = true in the command handler.
command由4部分組成:
命令: 表示應用程序的任務,並且跟蹤任務是否能執行(命令實際上不包含執行應用程序任務的代碼)
命令綁定:UI和命令的關聯
命令源:觸發命令的對象,比如菜單,按鈕
命令目標:在其中執行命令的元素,比如paste命令在TextBox中執行,TextBox就是命令目標
2. xaml中創建命令綁定
<!-- xaml中創建命令綁定:
1)添加想要的命令的命令綁定到窗口的命令綁定集合 -->
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open"
Executed="OpenCommand_Executed"
CanExecute="OpenCommand_CanExecute"/>
</Window.CommandBindings>
<!-- xaml中創建命令綁定:
2)UI通過Command屬性關聯到命令 -->
<Button Content="Open" Command="ApplicationCommands.Open" Margin="10" Grid.Row="1"/>
<!-- xaml中創建命令綁定:
3)後臺代碼處理OpenCommand_Executed/OpenCommand_CanExecute兩個事件 -->
private void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Open command triggered by " + e.Source.ToString());
}
private void OpenCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = false;
}
3.後臺創建命令綁定
public MainWindow()
{
InitializeComponent();
//後臺代碼創建命令綁定
CreateNewCommandBinding();
}
private void CreateNewCommandBinding()
{
//後臺代碼創建命令綁定:1)添加綁定到窗口
//創建綁定
CommandBinding binding = new CommandBinding(ApplicationCommands.New);
//添加事件處理
binding.Executed += NewCommand_Executed;
binding.CanExecute += NewCommand_CanExecute;
//註冊
this.CommandBindings.Add(binding);
}
//後臺代碼創建命令綁定:2)實現兩個事件NewCommand_Executed/NewCommand_CanExecute
private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("New command triggered by " + e.Source.ToString());
}
private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
<!-- 後臺代碼創建命令綁定:
3) xaml中,UI通過Command屬性關聯到命令 -->
<!--
<Button Content="New" Command="ApplicationCommands.New" Margin="10"/>
-->
<Button ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"
Command="ApplicationCommands.New" Margin="10">
<Image Source="1.gif" Height="16"/>
</Button>
4.使用微軟預定義好的命令
//1)xaml
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Cut"
CanExecute="CutCommand_CanExecute"
Executed="CutCommand_Executed" />
<CommandBinding Command="ApplicationCommands.Paste"
CanExecute="PasteCommand_CanExecute"
Executed="PasteCommand_Executed" />
</Window.CommandBindings>
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="3">
<Button Command="ApplicationCommands.Cut" Width="60">_Cut</Button>
<Button Command="ApplicationCommands.Paste" Width="60" Margin="3,0">_Paste</Button>
</WrapPanel>
<TextBox AcceptsReturn="True" Name="txtEditor" />
</DockPanel>
//2)code-behind
//下面兩個,一個是判斷命令是否可以執行,另一個是實際要執行的代碼
//實際上微軟爲預定義的command提供了默認的處理,
//所以如果想用默認處理,那麼下面的代碼都可以省掉不用寫。
private void CutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = (txtEditor != null) && (txtEditor.SelectionLength > 0);
}
private void CutCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
txtEditor.Cut();
}
//下面兩個,一個是判斷命令是否可以執行,另一個是實際要執行的代碼
private void PasteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = Clipboard.ContainsText();
}
private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
txtEditor.Paste();
}
5.自定義RoutedUICommand
//1)定義一個靜態類,用於放置我們自定義的所有命令
public static class CustomCommands
{
public static readonly RoutedUICommand Exit = new RoutedUICommand
(
"Exit",//text
"Exit",//name
typeof(CustomCommands),//owner type
new InputGestureCollection()//gesture collection
{
new KeyGesture(Key.F4, ModifierKeys.Alt)
}
);
//Define more commands here, just like the one above
}
//2)準備命令實際要執行的代碼,MainWindow.xaml.cs
private void ExitCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ExitCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
Application.Current.Shutdown();
}
<!-- 3)命令註冊到窗口,MainWindow.xaml -->
<Window.CommandBindings>
<CommandBinding Command="local:CustomCommands.Exit"
CanExecute="ExitCommand_CanExecute"
Executed="ExitCommand_Executed" />
</Window.CommandBindings>
<!-- 4)命令綁定到UI -->
<Grid x:Name="myGrid">
<!-- 菜單綁定到自定義的Exit命令 -->
<Menu>
<MenuItem Header="File">
<MenuItem Command="local:CustomCommands.Exit" />
</MenuItem>
</Menu>
<StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<!-- 按鈕也綁定到自定義的Exit命令 -->
<Button Command="local:CustomCommands.Exit" Width="160" Margin="0, 10, 0, 10">Exit</Button>
</StackPanel>
</Grid>
6.自定義ICommand
WPF所有命令都從ICommand派送實現,該接口有兩個方法和一個事件:
public interface ICommand
{
event EventHandler CanExecuteChanged;
bool CanExecute(object parameter);
void Execute(object parameter);
}
我們也可以從ICommand派生實現自己的Command。
//1)派生實現自定義command
public class CommandChangeColor : ICommand
{
#region ICommandInterface
public bool CanExecute(object parameter)
{//CommandParameter="{Binding ElementName=MainWnd}"
var control = parameter as Control;
if (null == control)
return false;
return true;
}
public void Execute(object parameter)
{
var control = parameter as Control;
var random = new Random();
byte r = (byte)random.Next(255);
byte g = (byte)random.Next(255);
byte b = (byte)random.Next(255);
SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(255, r, g, b));
control.Background = brush;
}
// Notice here: the events should be passed to the command manager to take care about it
//https://joshsmithonwpf.wordpress.com/2008/06/17/allowing-commandmanager-to-query-your-icommand-objects/
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
#endregion
}
//2)UI綁定命令
<!-- 按鈕綁定到自定義的CommandChangeColor命令, 並且傳了參數 -->
<Button Command="{StaticResource CommandChangeColor}"
CommandParameter="{Binding ElementName=MainWnd}"
Width="160" Margin="0, 10, 0, 10" Content="ChangeColor"/>