2010-08-10 5 views
5

Ho una casella di testo in cui ho questo: <KeyBinding Command="{Binding MyCommand}" Key="Tab"/>WPF: scorciatoia per il Tab, Tab rondini e Non passarlo insieme

problema è che inghiotte la scheda e non fa scheda al controllo successivo . Come posso intrappolare la scheda per la casella di testo e mantenere ancora il tabulazione al controllo successivo nell'ordine di tabulazione? Modifica: sto anche utilizzando MVVM e MyCommand è nel codice ViewModel, quindi è lì che devo ri-lanciare la scheda.

+1

Forse l'evento 'LostFocus' è più adatto ai tuoi scopi? (Continuo a considerare la tua domanda come interessante, quindi +1.) – Heinzi

+0

Ho guardato in LostFocus, ma con la mia modifica di Sto usando MVVM, mi piacerebbe non inserire il codice lì. – mike

+0

Sto pensando di più a LostFocus, come potrei associare il comando all'evento LostFocus? Voglio t questo senza inserire codice nel codice xaml dietro, solo vincolante per un comando nel mio ViewModel. – mike

risposta

0

Non riesco a trovare un modo per impostare lo stato attivo su un controllo data la tua domanda come soluzione puramente XAML.
Ho scelto di creare una proprietà attatta e quindi attraverso il binding impostare lo stato attivo sul controllo successivo dal comando associato al KeyBinding nel ViewModel.

Ecco la vista:

<Window x:Class="WarpTab.Views.MainView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:c="clr-namespace:WarpTab.Commands" 
    xmlns:Views="clr-namespace:WarpTab.Views" 
    xmlns:local="clr-namespace:WarpTab.ViewModels" 
    Title="Main Window" Height="400" Width="800"> 

    <Window.Resources> 
     <c:CommandReference x:Key="MyCommandReference" Command="{Binding MyCommand}" /> 
    </Window.Resources> 

    <DockPanel> 
    <ScrollViewer> 
     <WrapPanel > 
     <TextBox Text="First text value" > 
      <TextBox.InputBindings> 
       <KeyBinding Command="{StaticResource MyCommandReference}" Key="Tab"/> 
      </TextBox.InputBindings> 
     </TextBox> 
     <TextBox Text="Next text value" local:FocusExtension.IsFocused="{Binding FocusControl}" /> 
     <Button Content="My Button" /> 
     </WrapPanel> 
    </ScrollViewer> 
    </DockPanel> 
</Window> 

Ecco il ViewModel:

using System.Windows.Input; 
using WarpTab.Commands; 

namespace WarpTab.ViewModels 
{ 
    public class MainViewModel : ViewModelBase 
    { 
    public ICommand MyCommand { get; set; } 
    public MainViewModel() 
    { 
     MyCommand = new DelegateCommand<object>(OnMyCommand, CanMyCommand); 
    } 

    private void OnMyCommand(object obj) 
    { 
     FocusControl = true; 

     // process command here 

     // reset to allow tab to continue to work 
     FocusControl = false; 
     return; 
    } 

    private bool CanMyCommand(object obj) 
    { 
     return true; 
    } 

    private bool _focusControl = false; 
    public bool FocusControl 
    { 
     get 
     { 
     return _focusControl; 
     } 
     set 
     { 
     _focusControl = value; 
     OnPropertyChanged("FocusControl"); 
     } 
    } 
    } 
} 

ecco il codice per definire la proprietà associata che ho trovato nel seguente answer.

using System.Windows; 

namespace WarpTab.ViewModels 
{ 
    public static class FocusExtension 
    { 
    public static bool GetIsFocused(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(IsFocusedProperty); 
    } 

    public static void SetIsFocused(DependencyObject obj, bool value) 
    { 
     obj.SetValue(IsFocusedProperty, value); 
    } 

    public static readonly DependencyProperty IsFocusedProperty = 
      DependencyProperty.RegisterAttached(
      "IsFocused", typeof(bool), typeof(FocusExtension), 
      new UIPropertyMetadata(false, OnIsFocusedPropertyChanged)); 

    private static void OnIsFocusedPropertyChanged(DependencyObject d, 
      DependencyPropertyChangedEventArgs e) 
    { 
     var uie = (UIElement)d; 
     if ((bool)e.NewValue) 
     { 
     uie.Focus(); // Don't care about false values. 
     } 
    } 
    } 
} 
0

Perché non si utilizza questo codice nel gestore di comandi?

private void MyCommandHandler(){ 

    // Do command's work here 

    TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next); 
    request.Wrapped = true; 
    control.MoveFocus(request); 

} 

Questo è praticamente ciò che fa 'Tab', quindi se fai lo stesso, sei a posto. (Naturalmente invertire il senso se si dispone di un comando con Shift-Tab.

Io in realtà avvolto questo in un metodo di estensione in questo modo ...

public static class NavigationHelpers{ 

    public static void MoveFocus(this FrameworkElement control, FocusNavigationDirection direction = FocusNavigationDirection.Next, bool wrap = true) { 

     TraversalRequest request = new TraversalRequest(direction); 
     request.Wrapped = wrap; 
     control.MoveFocus(request); 

    } 

} 

... significa che il codice di prima diventa ancora più semplice , come questo ...

private void MyCommandHandler(){ 

    // Do command's work here 

    Control.MoveFocus(); 

} 

... e se non sai cosa quello attualmente attivo di controllo è, si può solo fare questo ...

(Keyboard.FocusedElement as FrameworkElement).MoveFocus(); 

Spero che questo aiuti! Se è così, è molto apprezzato se mi voti o contrassegnato come accettato!

+0

ViewModel non ha alcun FrameworkElement a cui spostare lo stato attivo. – Nick