繁体   English   中英

子视图集中在MVVM应用程序中以查看命令

[英]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的好处:

  1. 使您的命令了解按键手势
  2. 给KeyBinding一个利用(1)的附加属性

很明显,这是基础架构的一部分工作,一旦安装就可以测试和重用。 在这种情况下,由于您希望绑定在窗口级别可用,因此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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM