【问题标题】:Modifying a TextBox control on the Leave event prevents tabbing out of the control在 Leave 事件上修改 TextBox 控件可防止跳出控件
【发布时间】:2010-02-18 19:30:19
【问题描述】:

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

有人看到我做错了吗?

【问题讨论】:

  • 有趣.. 似乎是 TextAlign 的东西。如果我将其注释掉,似乎还可以。
  • +1 很好的发现。希望其中一种解决方法对您有用,尽管两者都不是最佳的。可能可以将此发布到 MSDN 论坛 (social.msdn.microsoft.com/Forums/en-US/categories) 看看他们是否知道发生了什么。

标签: c# .net winforms textbox


【解决方案1】:

看起来像是另一种方式(使用反射器查看它是否会重新聚焦到控件上,如果焦点在那里)。我认为这是一个错误,但看起来他们只是在重用 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;
     }
  }

【讨论】:

  • +1 用于花时间检查 Reflector 中实际发生的情况。
【解决方案2】:

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

这是一个快速修复:

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

(尽管对意外行为有些破解)。只需在更改对齐之前禁用控件即可。另一个“修复”是保持左对齐,或者测量插入多少空格来模拟文本居中。

【讨论】:

  • +1 :) 如果不出意外,我必须支持比尔同事!我使用focus 方法的唯一原因是它在我的机器上闪烁得少了一点。
【解决方案3】:

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

【讨论】:

  • +1。我选择 focus() 解决方案而不是这个解决方案的唯一原因是它使函数应该从它的定义中执行的操作离域。
  • 这个解决方案主要是“偶然”工作的,即,通常 BeginInvoke 委托将被安排为“稍后”调用,也就是说,在焦点从控件移开之后 - 但不能保证稍后 - OnLeave 代码实际上可以在 tbUsername_Leave 事件处理程序完成并且焦点从原始控件移开之前运行。
  • 不保证的证据在哪里?我只能重申 BeginInvoke 主要等同于 PostMessage 并将已注册的消息排入 Windows 消息队列中以供以后处理。然后它被应用程序消息泵拾取并在主 GUI 线程上执行。
猜你喜欢
  • 1970-01-01
  • 2019-09-08
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多