C# WPF:如果当前文本框被清除,如何聚焦到上一个文本框

4

我有一个项目,需要在用户继续删除时,如果当前字段为空,则聚焦于前一个字段。类似于在某处输入CD密钥的情况。您会有几个带有4-5个符号的块。如果您删除第三个文本框,例如,那么第三个文本框被清空后,您将被迫返回到第二个文本框。

if (textBox2.Text.Length == 0)
{
     Keyboard.Focus(textBox1);
}

这段代码本来可以正常运行,但是考虑到我还有另一个onfocus事件,所以textBox2一旦获得焦点就会变为空,由于上面的代码强制让焦点回到textBox1,因此它陷入了循环。

如果我理解正确,我需要捕捉按下Delete键,对吗?但问题在于我不知道如何插入这段代码。

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Delete)
    {
        if (textBox2.Text.Length == 0)
        {
             Keyboard.Focus(textBox1);
        }
    }
}

在这个函数内部:
private void textBox2_TextChanged(object sender, TextChangedEventArgs e)
{
     if (textBox2.Text.Length == 2)
     {
          Keyboard.Focus(textBox3);
     }
     // HERE I NEED SOMETHING LIKE ELSE IF (e.Key == Key.Delete) {...
}

请帮我,谢谢。 更新:我尝试了另一种解决方案,但它没有起作用:

private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
     if (e.Key == Key.Delete)
     {
          if (textBox2.Text.Length == 0)
          {
               Keyboard.Focus(textBox1);
          }
     }
}
3个回答

1
这里是针对任意数量的文本框的通用解决方案。
文本框列表的初始化:
private readonly List<TextBox> _textBoxes;

public MainWindow()
{
    InitializeComponent();

    _textBoxes = new List<TextBox> { _textBox1, _textBox2, _textBox3 };
}

带有KeyUp事件的版本:

private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Tab)
        return;

    var current = (TextBox)sender;
    if (current.Text.Any())
        return;

    var index = _textBoxes.IndexOf(current);
    if (index == 0)
        return;

    var previous = _textBoxes[index - 1];
    previous.Focus();
    previous.CaretIndex = previous.Text.Length;
}

以上版本不允许在按住场景中通过文本框进行跳转。为了解决这个问题,请使用TextChanged事件:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    var current = (TextBox)sender;
    if (current.Text.Any())
        return;

    var index = _textBoxes.IndexOf(current);
    if (index == 0)
        return;

    var previous = _textBoxes[index - 1];
    previous.Focus();
    previous.CaretIndex = previous.Text.Length;
}

第三种使用PreviewKeyDown的解决方案,仅支持Key.Delete:

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key != Key.Delete)
        return;

    var current = (TextBox)sender;
    if (current.Text.Length != 0)
        return;

    var index = _textBoxes.IndexOf(current);
    if (index == 0)
        return;

    var previous = _textBoxes[index - 1];
    previous.Focus();
    previous.CaretIndex = 0;
}

第四个解决方案同样使用PreviewKeyDown,支持Key.Delete和Key.Back:
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key != Key.Delete && e.Key != Key.Back)
        return;

    var current = (TextBox)sender;
    if (current.Text.Length != 0)
        return;

    var index = _textBoxes.IndexOf(current);
    if (index == 0)
        return;

    var previous = _textBoxes[index - 1];
    previous.Focus();

    if (e.Key == Key.Delete)
        previous.CaretIndex = 0;
}

新的List<TextBox>(new[] { _textBox1, _textBox2, _textBox3 }); 我不确定这里需要下划线。通常你的解决方案是有效的,但我对第二部分不清楚。为什么不能通过KeyDown事件来完成呢?这样我们就不需要任何TextChanged修复了。你有没有想过如何使我提供的代码与KeyDown一起工作?请告诉我。 - Mike
1
@Mike Key.Delete 和 Key.Back 不会发送到 KeyDown 事件处理程序,但是可以使用 PreviewKeyDown。 - Ryszard Dżegan
@Mike 我认为维护一个文本框列表比为每个文本框制作处理程序更具可扩展性、灵活性、可维护性,并且具有较少的逻辑重复。 - Ryszard Dżegan
谢谢!虽然我不太理解你在这里使用的每个东西,但它确实有效,我希望有一天它能变得完全清晰明了.. :) - Mike

0

终于,这个可以工作了:

private void textBox2_KeyUp(object sender, KeyEventArgs e)
{
     if (e.Key == Key.Delete)
     {
          if (textBox2.Text.Length == 0)
          {
          Keyboard.Focus(textBox1);
          }
     }
}

0

这个没有经过测试,但应该也能工作。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }        

    private void textBox2_KeyDown(object sender, KeyEventArgs e)
    {
        if (textBox2.Text == "")
        {
            textBox1.Focus();
        }
    }

    private void textBox3_KeyDown(object sender, KeyEventArgs e)
    {
        if (textBox3.Text == "")
        {
            textBox2.Focus();
        }
    }                  
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接