尝试在焦点/单击时选择 TextBox 中的所有文本

问题描述 投票:0回答:3

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

所以问题是当我使用 Enter focus 事件并应用 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
3个回答
5
投票

您需要结合 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
的调用发布到表单的消息队列中。 相关代码将在初始鼠标单击的所有消息处理完成后运行。


0
投票

我不确定您是否应该等待 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完全选择了

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


0
投票

就像浏览器的地址栏。 当您通过 Tab 键或鼠标单击/拖动将焦点集中到它时,它就会起作用。

internal static class Sub
{
    private static HashSet<object> _focusedTextbox = new HashSet<object>();
    internal static void setTextBoxSelectAllLikeBrowser(TextBox tb)
    {
        Debug.Assert(tb != null);

        // got focus
        tb.Enter += (sender, e) => {
            if (sender != tb || tb.IsDisposed) return; // to be safe

            // focused flag ON when mouse clicked
            if (Control.MouseButtons != MouseButtons.None) { // mouse clicked
                _focusedTextbox.Add(tb); return;
            }

            // without this, the entire selection won't be selected when you focus in with the tab key
            tb.SelectAll(); _focusedTextbox.Remove(tb);
        };

        // lost focus
        tb.Leave += (sender, e) => _focusedTextbox.Remove(tb);

        // mouse click
        tb.MouseDown += (sender, e) => {
            if (sender != tb || tb.IsDisposed) return; // to be safe
            if (!_focusedTextbox.Contains(tb)) return; // already in focus?

            // In the case of right-clicking, the MouseUp event does not arrive
            // until the context menu disappears, so it is handled here.
            if (e.Button == MouseButtons.Right) { // right clicked
                tb.SelectAll(); _focusedTextbox.Remove(tb);
            }
        };

        // mouse click end
        tb.MouseUp += (sender, e) => {
            if (sender != tb || tb.IsDisposed) return; // to be safe
            if (!_focusedTextbox.Contains(tb)) return; // already in focus?

            if (e.Button == MouseButtons.Left // left clicked
            && tb.SelectionLength <= 0) { // Without this, left dragging will select everything
                tb.SelectAll();
            }

            _focusedTextbox.Remove(tb);
        };
    }
}

// usage
internal partial class Form1 : Form
{
    private void Form1_Load(object sender, EventArgs e)
    {
        // when focus in a textbox, select all text like browser's address bar
        Sub.setTextBoxSelectAllLikeBrowser(textBox1);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.