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

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

我有一个包含 C# 中的

TextBox
的表单,我将其设置为字符串,如下所示:

textBox.Text = str;

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

c# winforms textbox
8个回答
153
投票

文本框的

TabIndex
为 0,并且
TabStop
设置为 true。这意味着当表单显示时,控件将获得焦点。

您可以为另一个控件指定 0

TabIndex
(如果有)并为文本框指定不同的选项卡索引 (>0),或者将文本框的
TabStop
设置为 false 以阻止这种情况发生。


48
投票

Windows 窗体中文本框的默认行为是,如果第一次通过按 Tab 键进入文本框获得焦点,则突出显示所有文本,但如果单击文本框,则不会突出显示所有文本。我们可以通过查看

TextBox
OnGotFocus()
覆盖来在 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;
    }
}

因此,如果您有一个文本框并按 Tab 键进入其中,则所有文本都将被选中。如果您单击它,突出显示将被删除,如果您重新插入它,您的插入符位置(和选择长度为零)将被保留。但是,如果我们以编程方式设置新的

Text
,并再次按 Tab 键进入文本框,那么所有文本将再次被选择。

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

第一个,可能也是最简单的,是通过在

selectionSet
表单上调用
DeselectAll()
并在
Load()
发生变化时简单地触发
Text
的设置:

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

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

(

DeselectAll()
只是将
SelectionLength
设置为零。实际上是
SelectionStart
翻转了
TextBox
selectionSet
变量。在上面的情况下,对
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() 中取消选择文本,但是如果用户按 Tab 键离开字段并返回,我们就会失去用户的突出显示。

丑吗?你打赌。但事实就是如此。


35
投票

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

SelectionStart
设置为
0
。问题解决了!

示例:

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

4
投票

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

视图->Tab 顺序

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

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


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 对话框遇到了同样的问题。似乎您可以通过从

FALSE
OnInitDialog()
返回
WM_INITDIALOG
来更改行为。希望这有帮助。


0
投票

这对我有用

public void SetNotes(string notes)
    {
        notesTextBox.Text = notes;

        notesTextBox.Select();
        notesTextBox.SelectionLength = 0;
        notesTextBox.SelectionStart = notes.Length;//place cursor at end of text
    }

0
投票

为什么不在设置文本后简单地调用“选择”?

this.myTextBox.Text = "something";
this.myTextBox.Select(0, 0);

这适用于我的 .NET 8:现在插入符号放置在文本的开头。

它起作用的原因:参见Nicholas的解释:文本框有一个内部标志

selectionSet
。如果此标志为
false
,则控件在第一次获得焦点时将选择全文。

方法

TextBox.Select
在内部将此标志设置为
true
。因此,选择被保留。

有点令人困惑的是

TextBox.SelectionStart
TextBox.SelectionLength
属性没有设置此标志。

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