2014-04-11 3 views
6

Ich habe ein kleines WPF-Fenster mit 2 TextBoxen mit TabIndex 0,1 und ich möchte den Fokus automatisch von der ersten TextBox auf die zweite verschieben, wenn ich die Eingabetaste drücke . Ich verwende MVVM Light.WPF und MVVM: So verschieben Sie den Fokus automatisch zum nächsten Steuerelement

Bemerkung: Dieser Beitrag ist nicht dupliziert. Hier verwende ich nicht den klassischen Ansatz mit Event-Handler, sondern MVVM-Pattern und wie Sie wissen, ist Code Behind in der Ansicht nicht erlaubt.

Ich fand eine Lösung, aber ich weiß nicht, ob es MVVM-Prinzip respektiert. Hier ist der Code:

The View

<Window x:Class="WpfMMVLight2.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
    xmlns:cmd ="http://www.galasoft.ch/mvvmlight" 
    Title="MainWindow" Height="350" Width="525" 
    DataContext="{Binding MainViewModel}"> 
    <Grid FocusManager.FocusedElement="{Binding ElementName=tb1}"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto"/> 
     <ColumnDefinition Width="70"/> 
    </Grid.ColumnDefinitions> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 

    <TextBlock Grid.Column="0" Text="Text 1" VerticalAlignment="Center"/> 
    <TextBox x:Name="tb1" Grid.Column="1" VerticalAlignment="Center" Margin="5"> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="KeyDown"> 
       <cmd:EventToCommand PassEventArgsToCommand="True" 
       Command ="{Binding KeyDownCommand, Mode=OneWay}"/> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </TextBox> 


    <TextBlock Grid.Column="0" Grid.Row="1" Text="Text 2" VerticalAlignment="Center"/> 
    <TextBox x:Name="tb2" Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Margin="5"> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="KeyDown"> 
       <cmd:EventToCommand PassEventArgsToCommand="True" 
      Command ="{Binding KeyDownCommand, Mode=OneWay}"/> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </TextBox> 

</Grid> 

Das Ansichtsmodell:

private ICommand _keydownCommand; 
public ICommand KeyDownCommand 
    { 
     get 
     { 
      if (_keydownCommand== null) 
       _keydownCommand= new DelegateCommand<KeyEventArgs>(KeyDownCommandExecute); 
      return _keydownCommand; 
     } 



    } 


    private void KeyDownCommandExecute(KeyEventArgs e) 
    { 
     if (e != null && e.Key == Key.Enter) 
     { 
     TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next); 
     request.Wrapped = true; 
     ((Control)e.Source).MoveFocus(request); 
    } 
    } 
}  

Ich weiß nicht, ob die Verwendung von "Control" Klasse in Ansichtsmodell erlaubt ist oder nicht

Antwort

11

Wie Sie MVVM verwenden, können Sie ein Verhalten für diesen Einsatz:

public class TabOnEnterBehavior : Behavior<TextBox> 
{ 

    protected override void OnAttached() 
    { 
    AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown; 
    } 

    private void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e) 
    { 
    if (e.Key == Key.Enter) 
    { 
     var request = new TraversalRequest(FocusNavigationDirection.Next); 
     request.Wrapped = true; 
     AssociatedObject.MoveFocus(request); 
    } 
    } 

    protected override void OnDetaching() 
    { 
    AssociatedObject.PreviewKeyDown -= AssociatedObject_PreviewKeyDown; 
    } 

} 

In XAML:

<TextBox> 
    <i:Interaction.Behaviors> 
    <wpfTest:TabOnEnterBehavior /> 
    </i:Interaction.Behaviors> 
</TextBox> 
+0

Es ist eine gute Lösung und es funktioniert gut. Danke –

+0

Danke für die gute Lösung. Ich habe sehr Textbox auf Projekt, kann ich dies für Standard-TextBox festlegen und nicht für alle Textfelder Verhalten hinzufügen? –

+0

@ ar.gorgin: Werfen Sie einen Blick auf diese Frage SO: http: // Stackoverflow.com/questions/1647815/how-to-add-a-Blend-Verhalten-in-einem-Stil-Setzer –

2

Fügen Sie einen PreviewKeyDown Event zu Ihrerhinzuzuerst: Fokus auf das nächste Element zu bewegen

<TextBox PreviewKeyDown="OnTextBoxKeyDown" /> 

Dann eine TraversalRequest erstellen:

private void OnTextBoxKeyDown(object sender, KeyEventArgs e) 
{ 
if (e.Key == Key.Return) 
{ 
    TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next); 
    MoveFocus(request); 
} 
} 

EDIT

Alternativ, wenn Sie einen Befehl bevorzugen, können Sie nur einstellen ein KeyBinding in Ihrer :

 <TextBox.InputBindings> 
      <KeyBinding Key="Enter" Command="{Binding YourCommand}" /> 
     </TextBox.InputBindings> 

Und einfach so etwas wie oben in Ihrer ICommand s Execute Logik.

Auch diese Frage hier: How do I simulate a Tab key press when Return is pressed in a WPF application?

+1

folgen I MVVM Muster . Ich denke, keine Ereignisse erlaubt. –

+0

Eigentlich benutze ich MVVM Light, die EventToCommand anbietet, Keydown Event in Command zu konvertieren. Aber mein Problem ist, wie man Focus zu Next TextBox bewegt, ohne EventHandler zu benutzen. –

+7

Auch hier geht es bei MVVM darum, die Sicht von der Logik zu trennen. Es geht nicht um extremistische "keine Ereignisse erlaubt". Sie versuchen hier, den Fokus zu verschieben, was eine reine UI-Aktion ist. Warum würden Sie ihn irgendwo anders als in der Benutzeroberfläche einsetzen (sei es xaml oder xaml.cs)? Denken Sie daran, sich zuerst daran zu erinnern: MVVM geht nicht um "kein Code-Behind" oder "keine Ereignisse", es geht um "kein Geschäft in UI-Logik". Sie sind berechtigt, Ereignisse dort zu verwenden :) – Damascus

Verwandte Themen