Modifying a TextBox control on the Leave event pre

2019-04-24 08:14发布

I've got a standard TextBox control which I'm trying to have mimic the "soft descriptions" like those found in the title and tags boxes on StackOverflow. Essentially, when the user's focus enters the control, it hides the description ("Username") in this case, and sets alignment and color to be that of a standard text control. When the user leaves the textbox, I want to check if the user actually entered anything, and put the username display back up otherwise.

For example:

    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";
        }
    }

Unfortunately, when I setup these events, the user cannot tab out of the username control. The control simply flickers and control returns to the textbox control itself until the user has entered something, skipping over the event body.

If I call this.SelectNextControl() in the event, then the event enters an infinite loop.

Does anybody see what I'm doing wrong?

3条回答
兄弟一词,经得起流年.
2楼-- · 2019-04-24 08:53

Setting the TextAlign property on the TextBox control returns focus back to that control. That seems like a bug.

Here is a quick fix:

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

(although somewhat of a hack around unexpected behavior). Simply disable the control before changing the alignment. Another "fix" would be to keep things aligned left, or to measure how many spaces to insert to simulate centering the text.

查看更多
该账号已被封号
3楼-- · 2019-04-24 08:59

Use 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";
        }
    }
查看更多
smile是对你的礼貌
4楼-- · 2019-04-24 09:00

Looks like another way around it (Using Reflector to see that it does refocus back on the Control if the focus was there to begin with). I think it is a bug, but looks like they were just reusing RecreateHandleCore function to redraw the text. So another way would be to focus off the textbox first, then continue:

  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;
     }
  }
查看更多
登录 后发表回答