これを行うには、ショートカットキーを受け取る添付プロパティを作成し、そのコントロールをホストするウィンドウに入力バインディングを作成します。これは少し複雑なクラスですが、非常に使いやすいです。
以下のプロジェクトに新しいクラスを追加することから始めます。
public class TextBoxHelper : DependencyObject
{
public class MvvmCommand : DependencyObject, ICommand
{
readonly Action<object> _execute;
readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public MvvmCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
if (execute == null) throw new ArgumentNullException("command");
_canExecute = canExecute == null ? parmeter => MvvmCommand.AlwaysCanExecute() : canExecute;
_execute = execute;
}
public object Tag
{
get { return (object)GetValue(TagProperty); }
set { SetValue(TagProperty, value); }
}
public static readonly DependencyProperty TagProperty = DependencyProperty.Register("Tag", typeof(object), typeof(MvvmCommand), new PropertyMetadata(null));
static bool AlwaysCanExecute()
{
return true;
}
public void EvaluateCanExecute()
{
EventHandler temp = CanExecuteChanged;
if (temp != null)
temp(this, EventArgs.Empty);
}
public virtual void Execute(object parameter)
{
_execute(parameter == null ? this : parameter);
}
public virtual bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
}
public static Key GetFocusKey(DependencyObject obj)
{
return (Key)obj.GetValue(FocusKeyProperty);
}
public static void SetFocusKey(DependencyObject obj, Key value)
{
obj.SetValue(FocusKeyProperty, value);
}
public static readonly DependencyProperty FocusKeyProperty =
DependencyProperty.RegisterAttached("FocusKey", typeof(Key), typeof(TextBoxHelper), new PropertyMetadata(Key.None, new PropertyChangedCallback((s, e) =>
{
UIElement targetElement = s as UIElement;
if (targetElement != null)
{
MvvmCommand command = new MvvmCommand(parameter => TextBoxHelper.FocusCommand(parameter))
{
Tag = targetElement,
};
InputGesture inputg = new KeyGesture((Key)e.NewValue);
(Window.GetWindow(targetElement)).InputBindings.Add(new InputBinding(command, inputg));
}
})));
public static void FocusCommand(object parameter)
{
MvvmCommand targetCommand = parameter as MvvmCommand;
if (targetCommand != null)
{
UIElement targetElement = targetCommand.Tag as UIElement;
if (targetElement != null)
{
targetElement.Focus();
}
}
}
}
XAMLでは、フォーカスキーを設定するために必要なのは、FocusKeyプロパティを割り当てることだけです。以下の例には2つのテキストボックスがあり、1つはF1が押されたときにフォーカスを取得し、もう1つはF7が押されたときにフォーカスを取得します。
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="131" Width="460">
<Grid Margin="10">
<TextBox Margin="0,0,0,60" local:TextBoxHelper.FocusKey="F1" />
<TextBox Margin="0,35,0,0" local:TextBoxHelper.FocusKey="F7" />
</Grid>
</Window>