2010-08-10 5 views
5

Pass Ich habe ein Textfeld, wo ich diese: <KeyBinding Command="{Binding MyCommand}" Key="Tab"/>WPF: KeyBinding für Tab, Tab Swallows und funktioniert es nicht Entlang

Problem ist es die Tab schluckt und nicht Tab zum nächsten Steuerelement . Wie kann ich die Registerkarte für das Textfeld abfangen und trotzdem die Tabulatorfunktion für das nächste Steuerelement in der Aktivierreihenfolge beibehalten? Edit: Ich verwende auch MVVM und MyCommand ist in der ViewModel-Code, so dass ich dort die Tab neu werfen muss.

+1

Vielleicht ist das Ereignis 'LostFocus' für Ihre Zwecke besser geeignet? (Ich denke immer noch, dass Ihre Frage von Interesse ist, also +1.) – Heinzi

+0

Ich habe LostFocus angeschaut, aber mit meiner Bearbeitung von MVVM möchte ich keinen Code dort einfügen. – mike

+0

Ich denke mehr über den LostFocus nach, wie könnte ich den Befehl an das LostFocus-Ereignis binden? Ich möchte das nicht tun, ohne Code in den XAML-Code hinter zu setzen, nur an einen Befehl in meinem ViewModel binden. – mike

Antwort

0

Ich kann keinen Weg finden, den Fokus auf eine Kontrolle zu setzen, die Ihre Frage als reine XAML-Lösung hat.
Ich beschließe, eine attacted Eigenschaft zu erstellen und dann durch Bindung den Fokus auf das nächste Steuerelement von dem Befehl, der mit Ihrer KeyBinding in dem ViewModel verknüpft ist, festzulegen. Hier

ist die Ansicht:

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

Hier ist das 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"); 
     } 
    } 
    } 
} 

Hier ist der Code, die beigefügte Eigenschaft zu definieren, die ich in den folgenden answer gefunden.

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

Warum verwenden Sie diesen Code nicht einfach in Ihrem Befehlshandler?

Das ist im Grunde, was "Tab" tut, also, wenn Sie das gleiche tun, sind Sie gut zu gehen. (Natürlich in umgekehrter Richtung, wenn Sie einen Befehl mit Shift-Tab haben.

ich eigentlich diese in eine Verlängerung Methode, wie so gewickelt ...

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

    } 

} 

... den Stand der Code mit der Bedeutung wird noch einfacher , so ...

private void MyCommandHandler(){ 

    // Do command's work here 

    Control.MoveFocus(); 

} 

... und wenn Sie nicht wissen, was die derzeit fokussierte Steuerung ist, können Sie einfach das tun ...

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

Hoffe das hilft! Wenn ja, sehr geschätzt, wenn Sie mich abstimmen oder es als angenommen markieren!

+0

Das ViewModel hat kein FrameworkElement, auf das der Fokus verschoben werden kann. – Nick