[英]Child view focus in MVVM application to see Command
我正在开发MVVM应用程序。 我有一个主窗口,看起来或多或少像这样:
<Window>
<ContentControl Content={Binding ContentViewModel} />
</Window>
然后,我有了这个ViewModel,它公开了一定数量的Command,并且我希望这些命令既可以从UI(带有按钮等)也可以从用户使用KeyBindings从键盘(对用户)可用。
这些命令可以从UI按钮正常工作。 但是键绑定并不总是有效,在我看来,问题在于加载的视图并非始终处于焦点位置。 这是该视图的代码。
<UserControl>
<UserControl.InputBindings>
<KeyBinding Key="Delete" Command="{Binding RemoveEntityCommand, ElementName=Designer}" />
</UserControl.InputBindings>
<Grid>
<namespace:Designer x:Name="Designer" />
</Grid>
</UserControl>
如何为MVVM应用永久解决此问题? 我已经多次遇到此问题。
注意:为简单起见,删除了所有名称空间声明。
谢谢。
我可能会将Command附加到Window
的KeyDown或KeyUp事件而不是UserControl
,然后从那里路由它。
可以将其路由到ShellViewModel
,然后在需要时将其传递给当前的ContentViewModel
,或者使用某种广播特殊键组合的消息系统,而ViewModel可以订阅它们。
我要做的是实现一个PreviewKeyUp事件,并使用该事件在我的视图模型上调用方法,如下所示:
protected void PreviewKeyUp(object sender, KeyEventArgs args)
{
args.Handled = myViewModel.HandleKeyUp(args.Key);
}
public bool HandleKeyUp(Key key)
{
// Determine if you should execute a command
if(myCommands.ShouldExecuteOnKey(key))
{
// Execute the commad
return true;
}
return false;
}
许多人似乎认为MVVM 并不意味着没有任何代码后置 ,但这并不总是正确的,甚至不可能。
是的,键绑定很痛苦。 我同意Rachel的观点,在这种特定情况下,您可能希望在窗口级别提供一些可用的功能。
您可以通过执行以下操作来避免出现代码隐藏并获得mvvm的好处:
很明显,这是基础架构的一部分工作,一旦安装就可以测试和重用。 在这种情况下,由于您希望绑定在窗口级别可用,因此ShellVm保留命令并根据需要委托给子视图模型。 我在下面只剩下了足够的代码,可以使您对该想法有所了解
HTH,
Berryl
<Window.InputBindings>
<cmdRef:KeyBindingEx CommandReference="{Binding AddCommand}"/>
</Window.InputBindings>
public class KeyBindingEx : KeyBinding
{
public static readonly DependencyProperty CommandReferenceProperty = DependencyProperty
.Register("CommandReference", typeof(CommandReference), typeof(KeyBindingEx),
new PropertyMetadata(OnCommandReferenceChanged));
private static void OnCommandReferenceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var kb = (KeyBinding) d;
var cmdRef = e.NewValue as VmCommand;
if(cmdRef==null) return;
kb.Key = cmdRef.GestureKey;
kb.Modifiers = cmdRef.GestureModifier;
kb.Command = cmdRef;
}
public CommandReference CommandReference
{
get { return (CommandReference)GetValue(CommandReferenceProperty); }
set { SetValue(CommandReferenceProperty, value); }
}
}
公共类CommandReference:PropertyChangedBase {...
public Key GestureKey
{
get { return _gestureKey; }
set
{
if (_gestureKey == value) return;
_gestureKey = value;
NotifyOfPropertyChange(() => GestureKey);
}
}
private Key _gestureKey;
}
/// <summary>A command whose primary purpose is to relay its functionality to other objects by invoking delegates.</summary>
public class VmCommand : CommandReference, ICommand
{
...
/// <summary>Action to be called when the Execute method of the command gets called</summary>
public Action ExecuteDelegate { get; protected set; }
/// <summary>Predicate to execute when the CanExecute of the command gets called (default is <c>true</c>)</summary>
public Func<bool> CanExecuteDelegate { get; protected set; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.