簡體   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