Изменение элемента управления TextBox в событии Leave предотвращает вкладывание из элемента управления - PullRequest
8 голосов
/ 18 февраля 2010

У меня есть стандартный элемент управления TextBox, который я пытаюсь имитировать «мягкими описаниями», подобными тем, которые находятся в полях заголовка и тегов в StackOverflow. По сути, когда фокус пользователя попадает в элемент управления, он в этом случае скрывает описание («Имя пользователя») и устанавливает выравнивание и цвет в соответствии со стандартным текстовым элементом управления. Когда пользователь покидает текстовое поле, я хочу проверить, действительно ли пользователь что-либо ввел, и в противном случае вернуть отображение имени пользователя.

Например:

    private void tbUsername_Enter(object sender, EventArgs e)
    {
        if (tbUsername.TextAlign == HorizontalAlignment.Center)
        {
            tbUsername.TextAlign = HorizontalAlignment.Left;
            tbUsername.ForeColor = SystemColors.ControlText;
            tbUsername.Text = String.Empty;
        }
    }

    private void tbUsername_Leave(object sender, EventArgs e)
    {
        if (tbUsername.Text == String.Empty)
        {
            tbUsername.TextAlign = HorizontalAlignment.Center;
            tbUsername.ForeColor = SystemColors.InactiveCaption;
            tbUsername.Text = "Username";
        }
    }

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

Если я вызываю this.SelectNextControl() в событии, то событие входит в бесконечный цикл.

Кто-нибудь видит, что я делаю не так?

Ответы [ 3 ]

6 голосов
/ 18 февраля 2010

Похоже по-другому (используя Reflector, чтобы увидеть, что он перефокусируется на элемент управления, если фокус был с самого начала). Я думаю, что это ошибка, но похоже, что они просто повторно использовали функцию RecreateHandleCore для перерисовки текста. Поэтому другим способом было бы сначала сфокусироваться на текстовом поле, а затем продолжить:

  private void LeaveEvent(object sender, EventArgs e)
  {
     if (String.IsNullOrEmpty(tbUsername.Text))
     {
        tbUsername.Text = USER_NAME;
        tbUsername.ForeColor = SystemColors.InactiveCaption;
        this.Focus();
        tbUsername.TextAlign = HorizontalAlignment.Center;
     }
  }
3 голосов
/ 18 февраля 2010

Использование BeginInvoke

    private void tbUsername_Leave(object sender, EventArgs e)
    {
        BeginInvoke(new MethodInvoker(OnLeave));
    }

    private void OnLeave()
    {
        if (tbUsername.Text == String.Empty)
        {
            tbUsername.TextAlign = HorizontalAlignment.Center;
            tbUsername.ForeColor = SystemColors.InactiveCaption;
            tbUsername.Text = "Username";
        }
    }
3 голосов
/ 18 февраля 2010

Установка свойства TextAlign в элементе управления TextBox возвращает фокус обратно этому элементу управления. Это похоже на ошибку.

Вот быстрое решение:

tbUsername.Enabled = false;
tbUsername.ForeColor = SystemColors.InactiveCaption;
tbUsername.Text = "Username";
tbUsername.TextAlign = HorizontalAlignment.Center;
tbUsername.Enabled = true;

(хотя что-то вроде взлома вокруг неожиданного поведения). Просто отключите элемент управления перед изменением выравнивания. Другим «исправлением» было бы выравнивание по левому краю или измерение количества пробелов, вставляемых для симуляции центрирования текста.

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