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

CJ7*_*CJ7 76 c# textbox winforms

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

textBox.Text = str;
Run Code Online (Sandbox Code Playgroud)

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

fle*_*her 116

文本框的a TabIndex为0并TabStop设置为true.这意味着在显示表单时将为焦点控件提供焦点.

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


Nic*_*cki 41

Windows窗体中TextBox的默认行为是突出显示所有文本,如果它第一次通过Tab键进行聚焦,而不是如果它被点击进入.我们可以通过观察在反射看到TextBoxOnGotFocus()覆盖:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是if语句导致我们不喜欢的行为.此外,为了增加对伤害的侮辱,无论何时重新分配文本,Text属性的设置者都会盲目地重置该selectionSet变量:

public override string Text
{
    get
    {
        return base.Text;
    }
    set
    {
        base.Text = value;
        this.selectionSet = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

第一个,也可能是最简单的,只需selectionSet通过调用DeselectAll()表单Load()Text更改时触发设置:

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

    this.textBox2.SelectionStart = this.textBox2.Text.Length;
    this.textBox2.DeselectAll();
}
Run Code Online (Sandbox Code Playgroud)

(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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你可能想要不打电话base.OnGotFocus(),但是我们会失去基Control类中的有用功能.而且你可能不想弄乱selectionSet废话,只是在OnGotFocus()中每次都取消选择文本,但如果他们从字段中退出并返回,我们就会失去用户的突出显示.

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


小智 28

这个问题的答案在类似的问题上给了我很多帮助,但简单的答案只是暗示了很多其他复杂的建议.设置文本后,只需将SelectionStart设置为0即可.问题解决了!

例:

yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
Run Code Online (Sandbox Code Playgroud)