Почему текст в TextBox выделяется (выделяется) при отображении формы? - PullRequest
74 голосов
/ 06 августа 2010

У меня есть форма, содержащая TextBox в C #, которую я установил в строку следующим образом:

textBox.Text = str;

Когда форма отображается, почему текст в текстовом поле отображается выделенным / выделенным?

Ответы [ 6 ]

114 голосов
/ 06 августа 2010

Текстовое поле имеет TabIndex, равное 0 и TabStop, установленное в значение true.Это означает, что элемент управления получит фокус при отображении формы.

Вы можете либо дать другому элементу управления 0 TabIndex (если он есть), а текстовому полю - другой индекс табуляции (> 0) или установите для TabStop значение false, чтобы текстовое поле не могло произойти.

41 голосов
/ 21 августа 2010

Поведение TextBox в Windows Forms по умолчанию состоит в том, чтобы выделить весь текст, если он фокусируется в первый раз, путем вкладывания в него, но не при нажатии на него. Мы можем увидеть это в Reflector, посмотрев на TextBox s OnGotFocus() override:

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 и снова перейдем в TextBox, тогда весь текст будет выделен снова.

Если вы похожи на меня и считаете это поведение раздражающим и непоследовательным, тогда есть два пути решения этой проблемы.

Первое, и, вероятно, самое простое, это просто запустить настройку 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 переворачивает selectionSet переменную TextBox. В приведенном выше случае вызов 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 (), но тогда мы потеряем выделение пользователя, если он выходит из поля и обратно.

Гадкий? Еще бы. Но это то, что есть.

26 голосов
/ 26 февраля 2013

Ответы на этот вопрос мне очень помогли с подобной проблемой, но на простой ответ намекают только многие другие сложные предложения. Просто установите SelectionStart на 0 после установки вашего текста. Проблема решена!

Пример:

yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
3 голосов
/ 11 апреля 2014

Вы также можете выбрать порядок вкладок для элементов управления вашей формы, открыв:

Вид-> Порядок табуляции

Обратите внимание, что эта опция доступна только в «Представлении», если у вас открыто представление «Дизайн формы».

Выбор «Порядка вкладок» открывает вид формы, который позволяет вам выбрать нужный порядок вкладок, нажимая на элементы управления.

1 голос
/ 03 июня 2015

Чтобы выделить текстовое поле, в VS 2013 попробуйте init с:

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

И добавить метод:

public void myTextBox_GotFocus(object sender, EventArgs e)
{
    myTextBox.SelectionLength=0;
}
0 голосов
/ 20 мая 2014

Я не проверял это на C #, но столкнулся с той же проблемой, используя диалоговое окно C ++ WIN32. Похоже, вы можете изменить поведение, возвращая FALSE из OnInitDialog () или WM_INITDIALOG. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...