【问题标题】:Try to select all text in TextBox when focus/clicked尝试在焦点/单击时选择 TextBox 中的所有文本
【发布时间】:2021-04-16 22:52:03
【问题描述】:

我尝试模仿用户单击用户名字段(例如)时的行为,并且所有文本(名称)将被自动选择,以便更容易用新文本替换它。但是当用户再次单击该字段时,文本/名称变为未选中状态,因此用户可以继续从光标处写入文本。我相信每个人都知道我要描述什么,因为当我们在文本字段中书写或想要修改其内容时,我们都遇到过很多次......

所以问题是当我使用 Enter 焦点事件并应用 SelectAll() 时,根本不工作!文本仍未选中。我也尝试使用 Click 事件,效果很好,但是我在第二次单击时遇到了困难,因为所有鼠标单击再次运行 SelectAll() 方法,文本始终仍处于选中状态.. 可能我可以使用存储选择状态的全局变量文本和更改状态反之亦然,但如果不需要,我不想使用任何额外的变量(每个都适用于所有 TextBox...不)。

应该有一个简单而优雅的解决方案,因为多对多应用程序和网站使用这种行为来使用户的生活更轻松。我阅读了一些论坛并找到了一些解决方案,但它们看起来比我希望的要复杂得多。

这是我的代码的相关部分...没什么特别的!

    private void G_tbx_canvasSize_Enter(object sender, EventArgs e)
    {
        (sender as TextBox).SelectAll();
    }

这应该以这种方式工作:

  • 用户点击文本框 (TB)
  • 专注于结核病
  • 代码运行并选择所有文本
  • 用户再次点击 TB
  • 由于这已经集中,代码将不会再次运行,因此默认情况下文本会取消选择自身。(我对此进行了测试!)
  • 如果用户点击离开并再次点击 TB,一切都会一次又一次地运行..

请帮忙!我无法弄清楚为什么会发生这种情况,任何问题,它不应该发生......

提前致谢!

【问题讨论】:

    标签: c# winforms events textbox click


    【解决方案1】:

    您需要结合 Enter 和 Click 事件。当处理程序连接到适当的事件时,此代码适用于我(在名为 textBox2 的文本框上):

    private bool textBox2JustEntered = false;
    private void textBox2_Enter(object sender, EventArgs e)
    {
        textBox2.SelectAll();
        textBox2JustEntered = true;
    }
    
    private void textBox2_Click(object sender, EventArgs e)
    {
        if (textBox2JustEntered)
        {
            textBox2.SelectAll();
        }
    
        textBox2JustEntered = false;
    }
    

    您希望单击事件仅在刚刚输入文本框时选择所有文本。 Enter 事件中额外的 SelectAll 调用存在,因为没有它,正常的“在此控件被选项卡到时选择所有文本”行为不会发生。

    @jimi 建议的替代方法是执行以下操作:

    private void textBox3_Enter(object sender, EventArgs e)
    {
        BeginInvoke(new Action(() => (sender as TextBox).SelectAll()));
    }
    

    这会将对SelectAll 的调用发布到表单的消息队列中。初始鼠标单击的所有消息处理完成后,相关代码将运行。

    【讨论】:

    • Enter 事件中只需要BeginInvoke(new Action(()=> (sender as TextBox).SelectAll()));
    • 在 UI 线程上调用的 BeginInvoke 在 UI 线程中工作,并且仅此而已。 MashaledInvoke 会处理这个问题。没有使用 ThreadPool 线程(我不明白您为什么认为应该参与其中)。从预期的封送处理程序(表单)调用的BeginInvoke 只是将消息排入消息循环中(异步 - 您不应从 UI 线程调用 Invoke())。
    • 我的立场是正确的。所以它实际上是一个很好的旧 Win32 PostMessage 调用
    • 是的,完全正确。经过几次检查以验证线程是否相同,PostMessage() 被调用。在这种情况下仅此而已。
    • 谢谢大家! “BeginInvoke”的东西就像一个魅力!非常简单的解决方案,正是我想要的。欣赏!
    【解决方案2】:

    我不确定您是否应该等待 GotFocus 事件。也许对 Enter 事件做出反应会更好。

    但即使您这样做,这也无济于事,因为在每个这些事件之后,您都会获得一个 TextBox.Click,这将取消选择您的文本。您将获得 TextBox.Click 事件。

    如果您经常使用具有这种特殊行为的 TextBox,请考虑创建一个派生自 TextBox 的 TextBoxWithSpecialClickBehaviour 类,并覆盖 OnEnter 和 OnClick。

    class TextBoxWithSpecialClickBehaviour : TextBox
    {
        public bool SelectAllTextOnGetFocus {get; set;} = true;
    
        // TODO: override some default behaviour
    }
    

    覆盖 OnEnter 和 OnClick

    protected override void OnEnter (EventArgs e)
    {
        // select all text
        if (this.SelectAllTextOnGetFocus)
            base.SelectAll();
    
         // raise the event
         base.OnEnter(e);
    }
    

    我认为您应该先选择文本,然后再通知其他人。因此,如果事件处理程序询问是否选择了文本,他们会得到正确的答案。但请注意,这些事件处理程序可能会再次取消选择文本。

    protected virtual void OnClick (EventArgs e)
    {
        if (this.SelectAllTextOnGetFocus)
        {
            // if nothing selected: select all, if anything selected: deselect all
            if (base.SelectionLength = 0)
                base.SelectAll();
            else
                base.SelectionLength = 0;
        }
        base.OnClick();
    }
    

    实验一下:覆盖 OnEnter 还是 OnGotFocus?也许您还需要设置 TextBox.SelectionStart。

    如果你不打算多次重复使用这个TextBox,对相应的事件做出反应就足够了。

    顺便说一句:你确定你想要这种行为吗?如果用户单击,然后开始编辑并单击编辑文本中的某个位置,因为他想选择一些文本以将其复制粘贴到他正在编辑的文本的不同部分,会发生什么情况。

    • 文本 ABCDEFG
    • 点击文本框ABCDEFG完全选中
    • 在 C 和 D 之间单击:未选择任何内容
    • 将鼠标拖到 F:ABCDEFG 选中
    • Ctrl C 复制文本。还必须选择文本吗?
    • 在 A 和 B 之间单击以粘贴文本。
    • 由于点击ABCDEFG完全被选中

    你确定要这个吗?运营商是否期望这一点?

    【讨论】:

      猜你喜欢
      • 2014-12-27
      • 2011-05-08
      • 1970-01-01
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 2012-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多