I've been looking for a while now and haven't found an easy or correct way to solve the following issue.
I have a multi-line TextBox with the ShortcutsEnabled = true
which, of course, allows the user to easily undo or redo any changes made by using the keyboard shortcuts (e.g. Ctrl + Z).
Now I wish to implement a button that clears the text of the TextBox but still allow the user to undo the action by using the default undo function.
Clearing the text from the TextBox is easy:
myTextBox.Clear();
//or
myTextBox.Text = string.Empty;
The problem is that the default undo function does not work when replacing the text these ways.
However, if the user selects all the text ( Ctrl + A ) and hits Delete manually, the TextBox becomes empty and the user can still restore the deleted data by Ctrl + Z.
I know that writing my own implementation of Undo
or Redo
would probably allow me to get the desired result but there has to be another way.
I simply need to be ably to mimic the manual select all and delete method in code.
And this is where I need some help, how can I implement this?
TextBox doesn't seem to have a default Delete, Remove or Replace text function that I can call.
As a proof of concept I've tried implementing this using the Cut
method (or Ctrl + X ) , which actually does what I want. The only downside is that this replaces potentially important clipboard data. I've tried coming up with a workaround for this as well, but after doing some research there doesn't seem to be any "correct" or at least "great" way to restore clipboard data.
var cbData = Clipboard.GetText();
myTextBox.SelectAll();
myTextBox.Cut();
Clipboard.Clear();
if(!string.IsNullOrEmpty(cbData))
Clipboard.SetText(cbData);
TLDR;
How can I delete the text from a TextBox in code the same way a user would do manually? So that the default Undo
method can still be called to restore the deleted text?
What about focusing the TextBox, selecting all text and then simulating a backspace? It's the same as the user manually clearing the TextBox. (Atleast, I clear text fields in this way)
textBox1.Focus();
textBox1.SelectAll();
SendKeys.Send("{BACKSPACE}");
A bit of partially relevant fact - In WPF, no matter how you change the text, the Undo and Redo methods always function properly.
Here is a bit hackish method, ask MS why such methods are not public.
public static class TextBoxUtils
{
// internal virtual void SetSelectedTextInternal(string text, bool clearUndo)
private static readonly Action<TextBox, string, bool> SetSelectedTextInternal =
(Action<TextBox, string, bool>)Delegate.CreateDelegate(typeof(Action<TextBox, string, bool>),
typeof(TextBox).GetMethod("SetSelectedTextInternal", BindingFlags.Instance | BindingFlags.NonPublic));
public static void UndoableClear(this TextBox target)
{
if (string.IsNullOrEmpty(target.Text)) return;
target.SelectAll();
SetSelectedTextInternal(target, string.Empty, false);
}
}
Usage
myTextBox.UndoableClear();
If you don't like hacks, you can use P/Invoke and send EM_REPLACESEL message which does not clear text editor internal undo buffer like WM_SETTEXT
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With