【问题标题】:Why is text in TextBox highlighted (selected) when form is displayed?为什么在显示表单时 TextBox 中的文本会突出显示(选中)?
【发布时间】:2011-03-26 04:30:18
【问题描述】:

我在 C# 中有一个包含 TextBox 的表单,我将其设置为如下字符串:

textBox.Text = str;

表单显示时,为什么texbox中的文字会高亮/选中?

【问题讨论】:

  • 您的问题可能与stackoverflow.com/questions/1140250/…有关
  • 您解决了吗?你是怎么解决这个问题的?
  • @fletcher:我还没来得及看它。我会在几天内给出答案。
  • 您可以添加一个 vb.net 标签,因为问题实际上是相同的,并且接受的答案也有效
  • BenSmith 的关于查看 Tab Order 的回答在这种情况下将非常有用。

标签: c# winforms textbox


【解决方案1】:

文本框的 TabIndex 为 0,TabStop 设置为 true。这意味着当窗体显示时,控件将获得焦点。

您可以给另一个控件 0 TabIndex(如果有)并给文本框一个不同的选项卡索引 (>0),或者将文本框的 TabStop 设置为 false 以阻止这种情况发生.

【讨论】:

  • 您确定文本框 TabIndex 设置为 0 吗?它源于它的行为?
  • @26071986 - 好吧,我进行了快速测试。如果在带有一个文本框和一个按钮的表单上,当 tabindex 设置为 0 时,我在构造函数中更改文本框中的文本,则文本将突出显示。如果按钮的标签索引为 0 且文本框的标签索引 >0,则文本不会突出显示。
  • 它确实似乎与 TabIndex 有关-只是我适当地更改了所有元素的标签索引(所以我想)。事实证明,Groups 也有标签索引,您需要更改它们以及它们的所有包含元素。因此,虽然我设置了 1-9 的元素选项卡,但一个组仍然有 0,因此该组中的文本框成为第一个激活的元素(因此其内容突出显示)。
  • 它不一定与 TabIndex = 0 相关,但如果 TextBox 具有表单的 LOWEST TabIndex,它肯定会发生。要验证:在 TextBox 中设置 TabIndex = 5,并在表单的其他控件的所有 TabIndex 中设置一个大于 5 的数字。
  • 当您在 TabControl 中选择新的 TabPage 时也会发生这种情况。相同的解决方案有效。
【解决方案2】:

Windows 窗体中 TextBox 的默认行为是在第一次通过 Tab 键获得焦点时突出显示所有文本,但如果单击它则不会。我们可以通过查看 TextBoxOnGotFocus() 覆盖在 Reflector 中看到这一点:

protected override void OnGotFocus(EventArgs e)
{
    base.OnGotFocus(e);
    if (!this.selectionSet)
    {
        this.selectionSet = true;
        if ((this.SelectionLength == 0) && (Control.MouseButtons == MouseButtons.None))
        {
            base.SelectAll();
        }
    }
}

正是 if 语句导致了我们不喜欢的行为。此外,雪上加霜的是,每当重新分配文本时,Text 属性的设置器都会盲目地重置 selectionSet 变量:

public override string Text
{
    get
    {
        return base.Text;
    }
    set
    {
        base.Text = value;
        this.selectionSet = false;
    }
}

因此,如果您有一个 TextBox 并在其中添加选项卡,则将选择所有文本。如果您单击它,突出显示将被删除,如果您重新进入它,您的插入符号位置(和零选择长度)将被保留。但是如果我们以编程方式设置新的Text,并再次tab进入TextBox,那么所有的文本都会再次被选中。

如果您像我一样发现这种行为令人讨厌且不一致,那么有两种方法可以解决这个问题。

第一个,可能也是最简单的,是通过在表单Load() 上调用DeselectAll() 以及每当Text 更改时简单地触发selectionSet 的设置:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    this.textBox2.SelectionStart = this.textBox2.Text.Length;
    this.textBox2.DeselectAll();
}

(DeselectAll() 只是将SelectionLength 设置为零。实际上是SelectionStart 翻转了TextBoxselectionSet 变量。在上述情况下,不需要调用DeselectAll(),因为我们是将开头设置为文本的结尾。但是如果我们将其设置为任何其他位置,例如文本的开头,那么调用它是一个好主意。)

更持久的方法是通过继承创建我们自己的具有所需行为的 TextBox:

public class NonSelectingTextBox : TextBox
{
    // Base class has a selectionSet property, but its private.
    // We need to shadow with our own variable. If true, this means
    // "don't mess with the selection, the user did it."
    private bool selectionSet;

    protected override void OnGotFocus(EventArgs e)
    {
        bool needToDeselect = false;

        // We don't want to avoid calling the base implementation
        // completely. We mirror the logic that we are trying to avoid;
        // if the base implementation will select all of the text, we
        // set a boolean.
        if (!this.selectionSet)
        {
            this.selectionSet = true;

            if ((this.SelectionLength == 0) && 
                (Control.MouseButtons == MouseButtons.None))
            {
                needToDeselect = true;
            }
        }

        // Call the base implementation
        base.OnGotFocus(e);

        // Did we notice that the text was selected automatically? Let's
        // de-select it and put the caret at the end.
        if (needToDeselect)
        {
            this.SelectionStart = this.Text.Length;
            this.DeselectAll();
        }
    }

    public override string Text
    {
        get
        {
            return base.Text;
        }
        set
        {
            base.Text = value;

            // Update our copy of the variable since the
            // base implementation will have flipped its back.
            this.selectionSet = false;
        }
    }
}

您可能想不调用base.OnGotFocus(),但这样我们将失去基类Control 中的有用功能。而且您可能很想完全不去搞乱selectionSet 的废话,并且每次在 OnGotFocus() 中简单地取消选择文本,但是如果用户在该字段之外并返回,我们将失去用户的突出显示。

丑吗?完全正确。但事实就是如此。

【讨论】:

    【解决方案3】:

    这个问题的答案对我解决类似问题有很大帮助,但简单的答案只是暗示了许多其他复杂的建议。设置文本后只需将SelectionStart 设置为0。问题解决了!

    例子:

    yourtextbox.Text = "asdf";
    yourtextbox.SelectionStart = 0;
    

    【讨论】:

      【解决方案4】:

      您还可以通过打开来选择表单控件的 Tab 键顺序:

      查看->标签顺序

      请注意,如果您打开了表单设计视图,则此选项仅在“视图”中可用。

      选择“Tab Order”会打开一个表单视图,让您可以通过单击控件来选择所需的 Tab 键顺序。

      【讨论】:

      • 这对我帮助很大。实际上,如果我们关注标签顺序,标签索引并不重要。
      【解决方案5】:

      要取消突出显示文本字段,在 VS 2013 中,尝试使用以下命令进行初始化:

      myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
      

      并添加方法:

      public void myTextBox_GotFocus(object sender, EventArgs e)
      {
          myTextBox.SelectionLength=0;
      }
      

      【讨论】:

      • 如果您之前聚焦文本框,选择其中的一些文本,移开它然后再次聚焦,这将导致文本被取消选择。
      【解决方案6】:

      我没有在 C# 上对此进行测试,但我在使用 C++ WIN32 对话框时遇到了同样的问题。似乎您可以通过从OnInitDialog()WM_INITDIALOG 返回FALSE 来更改行为。希望这会有所帮助。

      【讨论】:

      • 我认为这不会有太大帮助,因为 windows API 被封装在 winforms 中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-14
      • 2020-02-14
      相关资源
      最近更新 更多