Чому текст у TextBox виділяється (виділяється), коли відображається форма?


85

У мене є форма, що містить TextBoxв C #, яку я встановив як рядок наступним чином:

textBox.Text = str;

Чому при відображенні форми текст у текстовому полі відображається виділеним / виділеним?


Ваше питання може бути пов'язаний з stackoverflow.com/questions/1140250 / ...
DarenW

Вам вдалося з цим розібратися? Як ви це виправили?
fletcher

@fletcher: Я ще не розглянув це. Я присуджу відповідь за кілька днів.
CJ7,

Ви можете додати тег vb.net, оскільки проблема насправді однакова, і прийнята відповідь також є дійсною
Андреа Антонагелі

Відповідь BenSmith, пов’язана з переглядом порядку вкладок, буде дуже корисною у такому сценарії.
Саміта Чатуранга

Відповіді:


128

Текстове поле має TabIndexзначення 0 і має TabStopзначення true. Це означає, що елементу керування буде приділено увагу при відображенні форми.

Ви можете або дати іншому елементу керування 0 TabIndex(якщо він є) і призначити текстовому полі інший індекс вкладки (> 0), або встановити TabStopзначення false для текстового поля, щоб це не відбувалося.


1
Ви впевнені, що для текстового поля TabIndex встановлено значення 0? Це виходить з його поведінки?
26071986

@ 26071986 - Ну, я провів швидкий тест. Якщо на формі з одним текстовим полем і кнопкою я зміню текст у текстовому полі в конструкторі, коли для tabindex встановлено значення 0, текст виділяється. Якщо кнопка має індекс вкладки 0, а текстове поле tabindex> 0, текст не виділяється.
fletcher

Насправді, здається, це пов’язано з TabIndex - лише я відповідним чином змінив усі індекси вкладок своїх елементів (так я і думав). Виявляється, групи також мають індекси вкладок, які вам потрібно змінити, а також усі їх містять елементи. Тому, хоча я встановлював вкладки елементів з 1-9, у групі все ще було 0, тому текстове поле в цій групі стало першим активованим елементом (отже, його вміст було виділено).
deed02392

1
Це не обов'язково пов'язано з наявністю TabIndex = 0, але це, безумовно, трапляється, якщо TextBox має НАЙНІЖЧИЙ TabIndex форми. Для перевірки: встановіть TabIndex = 5 у TextBox та встановіть число більше 5 у всіх TabIndex інших елементів керування форми.
Андреа Антонагелі,

Це також трапляється, коли ви вибираєте нову TabPage у TabControl. Працює те саме рішення.
JonP

44

Поведінка TextBox за замовчуванням у Windows Forms полягає у виділенні всього тексту, якщо він вперше сфокусований, вклавши його, але не якщо його клацнути. Ми можемо побачити це в Reflector, подивившись на перевизначення TextBox' OnGotFocus():

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();
        }
    }
}

Це те, що твердження, яке спричиняє поведінку, яка нам не подобається. Крім того, щоб додати образи до травми, 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перевертає змінну 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 (), але тоді ми втратимо виділення користувача, якщо вони вийдуть із поля та назад.

Потворна? Ти робиш ставку. Але це те, що воно є.


31

Відповіді на це запитання мені дуже допомогли з подібною проблемою, але на просту відповідь натякають лише багато інших складних пропозицій. Просто встановіть SelectionStartзначення 0після налаштування тексту. Проблема вирішена!

Приклад:

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

4

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

Вигляд-> Порядок вкладок

Зверніть увагу, що цей параметр доступний лише в "Перегляді", якщо у вас відкрито подання дизайну форми.

Вибір "Порядок вкладок" відкриває вікно форми, яка дозволяє вибрати бажаний порядок вкладок, натиснувши на елементи керування.


1
Це мені дуже допомогло. Насправді індекс вкладки не має значення, чи стосується ми порядку вкладок.
Саміта Чатуранга

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. Сподіваюся, це допомагає.


1
Я не думаю, що це допоможе багато, оскільки API Windows інкапсульовано всередині винформ.
Натан А,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.