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

问题描述 投票:0回答:2

我有一个带有 2 个文本框的小 WPF 窗口,已订购 TabIndex 0,1,并且我想在按 Enter 键时自动将焦点从第一个文本框移动到第二个文本框。 我使用 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>

视图模型:

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

c# wpf mvvm
2个回答
18
投票

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

3
投票

首先将

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
中设置
TextBox
:

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

只需将与上面几乎相同的内容放入您的

ICommand.Execute()
逻辑中即可。

此外,这里还有同样的问题:在 WPF 应用程序中按下 Return 键时如何模拟 Tab 键按下?

© www.soinside.com 2019 - 2024. All rights reserved.