Дочерний вид фокус в приложении MVVM, чтобы увидеть команду - PullRequest
1 голос
/ 22 сентября 2011

Я занимаюсь разработкой приложения MVVM.У меня есть главное окно, которое выглядит примерно так:

<Window>
   <ContentControl Content={Binding ContentViewModel} />
</Window>

Затем у меня есть эта ViewModel, которая предоставляет определенное количество команд, и я хочу, чтобы эти команды были доступны пользователю как изпользовательский интерфейс (с кнопками и т. д.), а также с клавиатуры, используя привязки клавиш.

Команды работают правильно с кнопок пользовательского интерфейса.Но привязки клавиш не всегда работают, мне кажется, проблема в том, что загруженный вид не всегда в фокусе.Это код для представления.

<UserControl>
    <UserControl.InputBindings>
        <KeyBinding Key="Delete" Command="{Binding RemoveEntityCommand,  ElementName=Designer}" />
    </UserControl.InputBindings>
    <Grid>
        <namespace:Designer x:Name="Designer" />
    </Grid>
</UserControl>

Как решить это навсегда для приложения MVVM?Я сталкивался с этой проблемой несколько раз.

Примечание: все объявления пространства имен удалены для простоты.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 22 сентября 2011

Я бы, вероятно, прикрепил бы Command к событию KeyDown или KeyUp Window вместо UserControl и направил бы его оттуда.

Он может быть либо направлен на ShellViewModel, который, в свою очередь, передаст его текущему ContentViewModel, если необходимо, либо, возможно, использует какую-либо систему обмена сообщениями, которая передает специальные комбинации клавиш, и ViewModel может подписаться на них.

1 голос
/ 22 сентября 2011

Что я хотел бы сделать, это реализовать событие 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 означает без кода , но это не всегда так, или даже невозможно.

0 голосов
/ 22 сентября 2011

Да, привязки клавиш - это боль. И я согласен с Рэйчел в том, что в этом конкретном случае вы, вероятно, хотите что-то доступное на уровне окна.

Вы можете избежать кода и получить доброту mvvm, выполнив следующие действия:

  1. информируйте ваши команды о жестах клавиш
  2. дает связыванию ключей дополнительное свойство, которое использует (1)

Это, очевидно, небольшая инфраструктурная работа, так как она может быть проверена и повторно использована, когда она у вас есть. В этом случае, так как вы хотите, чтобы привязки были доступны на уровне окна, ваш ShellVm содержит команды и делегаты для дочерних моделей представления по мере необходимости. Я оставил достаточно кода, чтобы дать вам представление о идее

НТН,
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; }

}
...