[英]Handling input gestures in a user control (MVVM)
使用MVVM模式,如何處理按鍵手勢?
UserControl.InputBindings無法工作,因為它無法聚焦。
我定義了一個ICommand,當鍵入正確的鍵時應該調用該ICommand,但是如何將命令與View連接起來卻迷茫了。
謝謝,Stefan
我通過創建DelegateCommand類解決了這個問題。 它看起來完全像RelayCommand(請參見Josh Smith),但它允許更新回調。
public class DelegateCommand : ICommand
{
Action<object> _execute;
Predicate<object> _canExecute;
#region Constructors
public DelegateCommand()
{
}
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
public void Delegate(Action<object> execute)
{
_execute = execute;
}
public void Delegate(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? _execute != null : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
if (CanExecute(parameter))
_execute(parameter);
}
#endregion // ICommand Members
}
然后,我創建了一個用於容納靜態應用程序命令的類。
public class CustomCommands
{
private readonly static DelegateCommand admin;
static CustomCommands()
{
admin = new DelegateCommand();
}
public static DelegateCommand AdminCommand
{
get { return admin; }
}
}
然后,由於用戶控件未收到按鍵手勢,我向主窗口添加了按鍵綁定。
<Window.InputBindings>
<KeyBinding Key="A" Modifiers="Control" Command="my:CustomCommands.AdminCommand"/>
</Window.InputBindings>
然后,在我的ViewModel中,我可以像這樣處理事件:
public class OfflineViewModel : ViewModelBase
{
public OfflineViewModel()
{
CustomCommands.AdminCommand.Delegate(ShowAdmin);
}
public override void Removed()
{
base.Removed();
ReleaseAdminCommand();
}
public override void Hidden()
{
base.Hidden();
ReleaseAdminCommand();
}
void HookAdminCommand()
{
CustomCommands.AdminCommand.Delegate(ShowAdmin);
}
void ReleaseAdminCommand()
{
// Remove handling
CustomCommands.AdminCommand.Delegate(null, null);
}
void ShowAdmin(object parameter)
{
Navigation.Push(new AdminViewModel());
}
}
(可選)我可以在DelegateCommand內部使用事件。
這對我有效(.Net 4.0)
<UserControl>
<UserControl.InputBindings>
<KeyBinding Gesture="CTRL+C" Command="{Binding CancelCommand}" />
<KeyBinding Gesture="F5" Command="{Binding StartCommand}" />
<KeyBinding Gesture="CTRL+F5" Command="{Binding FreshStartCommand}" />
<KeyBinding Gesture="F10" Command="{Binding ContinueCommand}" />
<KeyBinding Gesture="F9" Command="{Binding RepeatCommand}" />
<KeyBinding Gesture="ALT+F4" Command="{Binding CloseCommand}" />
<KeyBinding Gesture="CTRL+N" Command="{Binding NewUUTCommand}" />
</UserControl.InputBindings>
....
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Center">
<Button x:Name="BtnStart" Content="STARTEN" Command="{Binding StartCommand}"/>
<Button Content="STOP" Command="{Binding StopCommand}"/>
</StackPanel>
....
<FocusManager.FocusedElement>
<Binding ElementName="BtnStart"/>
</FocusManager.FocusedElement>
</UserControl>
技巧是確保將焦點設置到UserControl中。 對我來說,這不是自動發生的。 一旦設置了焦點,則KeyBinding將起作用。 (注意,焦點必須設置在最后,因為必須先定義元素)
為了完整起見,這是ViewModel代碼。
public ICommand StartCommand
{
get
{
if (this._startCommand == null)
{
this._startCommand = new Mvvm.RelayCommand(parm => DoStart(), parm => DoCanStart());
} return this._startCommand;
}
}
private bool DoCanStart()
{
return !IsRunning && ReadyToRun;
}
private void DoStart()
{
log.Debug("Start test");
...
}
請看以下示例: http : //tomlev2.wordpress.com/2009/03/17/wpf-using-inputbindings-with-the-mvvm-pattern/
它使用XML標記將其綁定到DataContext of the root element
。 希望對您有幫助。
此解決方案有一個局限性:它僅適用於XAML根的DataContext。 因此,例如,您不能使用它在其DataContext也被重新定義的控件上定義InputBinding,因為標記擴展將訪問根DataContext。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.