2011-05-05 3 views
2

MVVM 패턴을 사용하여 키 동작을 어떻게 처리합니까?사용자 정의 컨트롤 (MVVM)에서 입력 제스처 처리

UserControl.InputBindings는 포커스를 가질 수 없으므로 작동하지 않습니다.

올바른 키를 입력 할 때 호출해야하는 ICommand를 정의했지만보기와 명령을 연결하는 방법이 손실되었습니다.

감사합니다,이 예에서 스테판

답변

3

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; } 
    } 
} 

사용자가 키 제스처를받지 못하기 때문에 기본 창에 키 바인딩을 추가했습니다.

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 내부 이벤트를 사용할 수 있습니다

<Window.InputBindings> 
    <KeyBinding Key="A" Modifiers="Control" Command="my:CustomCommands.AdminCommand"/> 
</Window.InputBindings> 

그런 다음 내 뷰 모델에서이 같은 이벤트를 처리 할 수 ​​있습니다.

이 나를 위해 작동
0

봐 : http://tomlev2.wordpress.com/2009/03/17/wpf-using-inputbindings-with-the-mvvm-pattern/

그것은 XML 마크 업으로 DataContext of the root element에 결합한다. 희망, 그것은 당신을 돕는다.

이 솔루션에는 제한이 있습니다. XAML 루트의 DataContext에 대해서만 작동합니다. 예를 들어, 태그 확장이 루트 DataContext에 액세스하므로 DataContext가 재정의 된 컨트롤에서 InputBinding을 정의하는 데 사용할 수 없습니다.

+0

아니요. 문제를 해결할 수 없습니다 :( – Vincent

+0

@Priyank, 앞의 링크가 깨졌습니다. – Elangesh

1

(닷넷 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"); 
    ... 
}