简体   繁体   English

WPF和MVVM:如何自动将焦点移动到下一个控件

[英]WPF and MVVM : How to move focus to the next Control automatically

I have a little WPF Window with 2 TextBoxes Having Ordered TabIndex 0,1 and i want to move focus automatically from the first TextBox to the second when i press Enter Key. 我有一个带有2个TextBoxes的WPF窗口,它有Ordered TabIndex 0,1我希望在按Enter键时自动将焦点从第一个TextBox移动到第二个TextBox。 I Use MVVM Light. 我使用MVVM Light。

Remark : This post is not duplicated. 备注:这篇文章不重复。 here I do not use Classic approach with event Handler but MVVM Pattern and as you know Code Behind is not allowed in view. 在这里,我不使用事件处理程序的经典方法,但MVVM模式,因为你知道在视图中不允许使用Code Behind。

I Found a solution but I don't know if it respect MVVM Principle. 我找到了解决方案,但我不知道它是否尊重MVVM原则。 Here the 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>

The ViewModel : ViewModel:

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

I don't know if use of "Control" Class in ViewModel Is allowed or not 我不知道是否允许在ViewModel中使用“Control”类

As you are using MVVM, you can use a Behavior for this: 当您使用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;
  }

}

In your xaml: 在你的xaml中:

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

Add a PreviewKeyDown event to your TextBox first: 首先在TextBox添加一个PreviewKeyDown事件:

<TextBox PreviewKeyDown="OnTextBoxKeyDown" />

Then create a TraversalRequest to move focus to the next item: 然后创建一个TraversalRequest以将焦点移动到下一个项目:

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

EDIT 编辑

Alternatively, if you prefer using a Command, you can just set a KeyBinding in your TextBox : 或者,如果您更喜欢使用Command,则可以在TextBox设置KeyBinding

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

And just put pretty much the same thing as above in your ICommand s Execute` logic. 并且在ICommand s Execute`逻辑中添加与上面相同s内容。

Also, same question here: How do I simulate a Tab key press when Return is pressed in a WPF application? 此外,同样的问题: 如何在WPF应用程序中按下Return键时模拟Tab键按下?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM