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

本文关键字:转移 焦点 下一个 控件 何自动 MVVM WPF | 更新日期: 2023-09-27 17:57:56

我有一个小的WPF窗口,其中有2个TextBoxes Having Ordered TabIndex 0,1,当我按下Enter键时,我想自动将焦点从第一个TextBox移动到第二个。我使用MVVM Light。

备注:此帖子不重复。在这里,我不使用事件处理程序的经典方法,但MVVM模式和代码隐藏在视图中是不允许的。

我找到了一个解决方案,但我不知道它是否尊重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>

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

我不知道是否允许在ViewModel中使用"Control"类

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

当您使用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>

首先向TextBox添加PreviewKeyDown事件:

<TextBox PreviewKeyDown="OnTextBoxKeyDown" />

然后创建一个TraversalRequest,将焦点转移到下一个项目:

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

编辑

或者,如果您喜欢使用命令,您可以在TextBox:中设置KeyBinding

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

只需在ICommand s执行逻辑中放入与上述内容大致相同的内容。

同样的问题是:当在WPF应用程序中按下Return时,我如何模拟Tab键的按下?