2014-04-11 129 views
6

我有一個WPF窗口,有2個TextBoxes命令TabIndex 0,1,我想從第一個TextBox自動移動焦點到第二個,當我按Enter鍵。 我使用MVVM Light。WPF和MVVM:如何將焦點自動移動到下一個控件

備註:此帖未重複。在這裏,我不使用經典的方法處理事件處理程序,但MVVM模式,因爲你知道Code Behind不允許在視圖中。

我找到了一個解決方案,但我不知道它是否尊重MVVM原則。 下面的代碼:

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

視圖模型:

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

我不使用,如果在視圖模型 「控制」 類是允許的或不知道

回答

11

當你使用MVVM,您可以使用此行爲:

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

} 

在您的XAML:

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

這是一個很好的解決方案,它工作正常。謝謝 –

+0

感謝您的好解決方案。我在項目上有非常的文本框,我可以將它設置爲默認的TextBox並且不爲所有文本框添加行爲? –

+0

@ ar.gorgin:看看這個SO問題:http:// stackoverflow。com/questions/1647815/how-to-add-a-blend-behavior-in-a-style-setter –

2

PreviewKeyDown事件添加到您的TextBox第一:

<TextBox PreviewKeyDown="OnTextBoxKeyDown" /> 

然後創建一個TraversalRequest將焦點移動到下一個項目:

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

編輯

或者,如果你喜歡使用命令,你可以設置一個KeyBinding in your TextBox

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

只需在您的ICommand s Execute邏輯中放置與上面幾乎相同的東西。

而且,同樣的問題在這裏:How do I simulate a Tab key press when Return is pressed in a WPF application?

+1

我遵循MVVM模式。我認爲不允許任何事件。 –

+0

實際上,我使用MVVM Light提供的EventToCommand將Keydown事件轉換爲Command。但我的問題是如何將焦點移到下一個TextBox而不使用EventHandler。 –

+7

同樣,MVVM是關於將視圖與邏輯分離的。這不是關於極端主義的「不允許的事件」。你在這裏試圖移動焦點,這是一個純粹的UI操作,爲什麼你會把它放在任何地方,但在用戶界面(可能是XAML或XAML.cs)?首先記住這一點:MVVM不是關於「沒有代碼隱藏」或「沒有事件」,而是關於「在UI邏輯中沒有業務」。您完全有權在此處使用活動:) – Damascus

相關問題