在Leave事件上修改TextBox控件可防止跳出控件

我有一个标准的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() ,则事件进入无限循环。

有人看到我做错了吗?

看起来像是另一种方式(使用Reflector看到它确实重新聚焦在Control上,如果焦点在那里开始)。 我认为这是一个错误,但看起来他们只是重新使用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; } } 

在TextBox控件上设置TextAlign属性会将焦点返回到该控件。 这似乎是一个错误。

这是一个快速修复:

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

(虽然有点出乎意料的行为)。 只需在更改对齐之前禁用控件。 另一个“修复”是将事物保持对齐,或者测量要插入多少空格以模拟文本居中。

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