为什么显示表单时TextBox中的文本突出显示(选中)?


84

我有一个包含TextBoxC#的表单,我将其设置为字符串,如下所示:

textBox.Text = str;

显示表单时,为什么texbox中的文本突出显示/选中?



您设法解决了吗?您是如何解决的?
fletcher 2010年

@fletcher:我还没有全面了解它。我将在几天后给出答案。
CJ7

您可以添加vb.net标记,因为问题实际上是相同的,并且接受的答案也有效
Andrea Antonangeli 2014年

在这种情况下,BenSmith与查看Tab键顺序有关的答案将非常有用。
Samitha Chathuranga 2015年

Answers:


128

文本框的aTabIndex为0,并TabStop设置为true。这意味着显示表单时,控件将获得焦点。

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


1
您确定文本框TabIndex设置为0吗?它是出于其行为?
26071986'8

@ 26071986-好,我进行了一次快速测试。如果在一个带有一个文本框和一个按钮的表单上,当tabindex设置为0时,我在构造函数的文本框中更改了文本,则文本将突出显示。如果按钮的标签索引为0,且文本框标签索引> 0,则文本不会突出显示。
fletcher 2010年

确实确实与TabIndex有关-只有我适当地更改了所有元素的Tab索引(所以我认为)。事实证明,组也具有需要更改的标签索引以及所有包含的元素。因此,当我从1-9设置元素选项卡时,一个组仍然具有0,因此该组中的文本框成为第一个激活的元素(因此其内容突出显示了)。
deed02392

1
它不一定与TabIndex = 0有关,但是如果TextBox具有表单的最低TabIndex,则肯定会发生这种情况。验证:在TextBox中设置TabIndex = 5,并在窗体的其他控件的所有TabIndex中将数字设置为大于5。
Andrea Antonangeli 2014年

当您在TabControl中选择一个新的TabPage时,也会发生这种情况。相同的解决方案有效。
JonP

43

Windows窗体中TextBox的默认行为是突出显示所有文本,如果您第一次通过将其突出显示来将其突出显示,则将其突出显示,而不是将其单击时则突出显示。通过查看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并在其中使用制表符,则将选中所有文本。如果单击它,则突出显示将被删除,如果重新选择它,则将保留插入符号位置(选择长度为零)。但是,如果我们以编程方式设置new Text,然后再次使用Tab键进入TextBox,则所有文本将再次被选中。

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

第一种,也许是最简单的方法,是selectionSet通过调用DeselectAll()formLoad()并在Text发生任何更改时简单地触发设置:

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()中都只是取消选择文本,但是如果用户跳出字段并返回,则会丢失用户的突出显示。

丑陋?完全正确。但是它就是这样啊。


31

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

例:

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

4

您还可以通过以下方式选择表单控件的选项卡顺序:

查看->标签顺序

请注意,只有打开了表单设计视图,此选项才在“视图”中可用。

选择“制表顺序”将打开窗体的视图,该视图允许您通过单击控件来选择所需的制表顺序。


1
这对我很有帮助。实际上,如果我们关注标签顺序,则标签索引并不重要。
Samitha Chathuranga 2015年

1

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

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

并添加方法:

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

如果您先前将文本框放在文本框上,在其中选择了一些文本,将其移开然后又重新聚焦,则这将导致取消选择文本。
斯图尔特

0

我尚未在C#上对此进行测试,但是使用C ++ WIN32对话框遇到了相同的问题。看来您可以通过FALSEOnInitDialog()或返回来更改行为WM_INITDIALOG。希望这可以帮助。


1
我认为这不会有太大帮助,因为Windows API封装在winforms中。
弥敦道A
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.