textBox对象的文本更改事件:如何执行文本更改+其他操作

本文关键字:文本 执行 操作 其他 对象 事件 textBox 何执行 | 更新日期: 2023-09-27 18:28:22

我希望当用户键入/更改textBox1的文本时,同时清除第二个textBox2的文本。为此,我只需在表单中添加一个事件:

private void textBox1_TextChanged(object sender, EventArgs e)
    {
        this.textBox2.Text = "";
    }

然而,这会导致textBox2被清除,但用户键入的输入会丢失。实际上:

我的期望:如果textBox1文本为空,而textBox2不为空,当用户在第一个文本框中键入"A"时,我将同时清除textBox2,并在textBox1中键入字母"A"。

我得到的:textBox2变清楚了,但字母"A"没有出现在textBox1中:我必须再打一次才能把它放在正确的位置。

在清除textBox2的同时,我应该做些什么来保持用户对textBox1的输入?

编辑:实际上忘记添加代码的一个重要部分,这是我上面发布的方法的"双胞胎"兄弟:

private void textBox2_TextChanged(object sender, EventArgs e)
    {
        this.textBox1.Text = "";
    }

我稍微修正了我的问题:如何在避免textBox2中的清除被视为text_changed事件的同时满足我的预期行为?

textBox对象的文本更改事件:如何执行文本更改+其他操作

我建议保持处理程序的整洁,而不是做两件事之一:

  • 使用Modified属性检查用户是否实际修改了文本框。当对Text进行编程更改时,此bool会自动恢复为false
  • 改为绑定到键盘事件

使用Modified

以下是如何实现前一个选项:

public void TextBox1_TextChanged(object sender, EventArgs ea)
{
    if (textBox1.Modified) textBox2.Clear(); 
}

这工作得很好,对于任何查看代码的人来说都很容易理解。如果以编程方式更改了Text属性(在您的情况下,由其他事件处理程序更改),则Modified属性为false,并且不会进行清除。

额外的好处是,如果您在其他地方进行编程更改,并且确实希望事件处理程序执行,则可以轻松地显式设置Modified = true

textBox1.Text = @"I have been set programmatically, 
                  but in this specific case the other box 
                  should still be cleared";
textBox1.Modified = true;

使用键盘事件

以下是如何使用键盘事件实现这一点:

private void TextBox1_TextChanged(object sender, EventArgs e)
{
    textBox2.Clear();
}

以及在哪里执行事件处理程序到事件绑定:

textBox1.KeyDown += TextBox1_TextChanged;
textBox1.Paste += TextBox1_TextChanged;

其他改进

通过添加一个将文本框清除逻辑绑定到任何其他文本框的方法,可以使其更通用。以下是我如何在我的测试winforms项目中使用它:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        ClearOnUserInput(textBox1, textBox2);
        ClearOnUserInput(textBox2, textBox1);
    }
    private void ClearOnUserInput(TextBox inputBox, TextBox target)
    {
        inputBox.TextChanged += delegate {
            if(inputBox.Modified) target.Clear();
        };
    }
}

请注意,我添加了一个单独的方法来附加清除逻辑以保持干燥,并且我还在这里使用匿名委托来避免添加额外的方法。您可以像以前一样轻松地使用两个处理程序。

您可以禁用事件处理程序以避免一个事件干扰另一个事件
你也可以使用全局布尔变量,但我更喜欢这种方法,因为它不需要全局和ifs-

private void textBox1_TextChanged(object sender, EventArgs e)
{
    this.textBox2.TextChanged -= textBox2_TextChanged;
    this.textBox2.Text = "";
    this.textBox2.TextChanged += textBox2_TextChanged;
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
    this.textBox1.TextChanged -= textBox1_TextChanged;
    this.textBox1.Text = "";
    this.textBox1.TextChanged += textBox1_TextChanged;
}

textBox1TextChanged事件中更改textBox2的文本时,会触发textBox2TextChanged事件,进而将textBox1文本设置为""

为了解决这个问题,您可以在更改文本之前删除每个处理程序中相反的TextChanged处理程序,然后将其放回:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    this.textBox2.TextChanged -= textBox2_TextChanged;
    this.textBox2.Text = "";
    this.textBox2.TextChanged += textBox2_TextChanged;
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
    this.textBox1.TextChanged -= textBox1_TextChanged;
    this.textBox1.Text = "";
    this.textBox1.TextChanged += textBox1_TextChanged;
}

您使用的是Text Changed事件,因此考虑在文本框中有一个字符:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    if (textBox1.Text.Length == 1 && textBox2.Text != String.Empty)
        textBox2.Text = String.Empty;
}

我建议您在您的场景中使用Key Down事件。它会在更改文本框的Text之前启动,并且会在正确的时间检查您的条件。

如果您试图只允许一个文本框接受输入,并始终清除另一个,则可以跟踪代码是否在单独的变量中更改文本。

示例:

// This variable tracks whether or not our code is changing the text
// If it's set to false, then the user is changing the text
private bool ignoreTextChange = false;
private void textBox1_TextChanged(object sender, EventArgs e)
{
    if (ignoreTextChange)
    {
        // Our code is changing the text, so just reset the variable
        ignoreTextChange = false;
    }
    else
    {
        // Our code is going to change the other text box,
        // so set our variable and clear the other text box
        ignoreTextChange = true;
        this.textBox2.Text = "";   
    }        
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
    if (ignoreTextChange)
    {
        ignoreTextChange = false;
    }
    else
    {
        ignoreTextChange = true;
        this.textBox1.Text = "";
    }  
}