Comment effacer une zone de texte pour que la méthode d’annulation par défaut fonctionne toujours?

Je cherche depuis un moment et je n’ai pas trouvé de moyen facile ou correct de résoudre le problème suivant.

J’ai une zone de texte multiligne avec ShortcutsEnabled = true qui, bien sûr, permet à l’utilisateur d’annuler ou de rétablir facilement toute modification effectuée à l’aide des raccourcis clavier (par exemple, Ctrl + Z ).
Maintenant, je souhaite implémenter un bouton qui efface le texte de la zone de texte, tout en permettant à l’utilisateur d’annuler l’action à l’aide de la fonction d’annulation par défaut.

Effacer le texte de la zone de texte est facile:

 myTextBox.Clear(); //or myTextBox.Text = ssortingng.Empty; 

Le problème est que la fonction d’annulation par défaut ne fonctionne pas lors du remplacement du texte de cette manière.
Toutefois, si l’utilisateur sélectionne tout le texte ( Ctrl + A ) et appuie sur Supprimer manuellement, la zone de texte devient vide et l’utilisateur peut toujours restaurer les données supprimées avec Ctrl + Z.

Je sais qu’écrire ma propre implémentation de Undo ou Redo me permettrait probablement d’obtenir le résultat souhaité, mais il doit y avoir un autre moyen.
Je dois simplement être capable de mimer le manuel tout sélectionner et supprimer la méthode dans le code.

Et c’est là que j’ai besoin d’aide, comment puis-je mettre cela en œuvre?

TextBox ne semble pas avoir une fonction de texte Supprimer , Supprimer ou Remplacer par défaut que je puisse appeler.
Comme preuve de concept, j’ai essayé d’implémenter cela à l’aide de la méthode Cut (ou Ctrl + X ), qui fait ce que je veux. Le seul inconvénient est que cela remplace les données potentiellement importantes du Presse-papiers. J’ai aussi essayé de trouver une solution à ce problème, mais après quelques recherches, il ne semble pas y avoir de moyen “correct” ou au moins “génial” de restaurer les données du Presse-papiers.

 var cbData = Clipboard.GetText(); myTextBox.SelectAll(); myTextBox.Cut(); Clipboard.Clear(); if(!ssortingng.IsNullOrEmpty(cbData)) Clipboard.SetText(cbData); 

TLDR;

Comment puis-je supprimer le texte d’une zone de texte dans le code de la même manière qu’un utilisateur le ferait manuellement? Pour que la méthode Undo par défaut puisse toujours être appelée pour restaurer le texte supprimé?

Pourquoi ne pas concentrer la zone de texte, sélectionner tout le texte puis simuler un retour arrière? C’est la même chose que l’utilisateur effaçant manuellement la zone de texte. (Au moins, j’efface les champs de texte de cette façon)

 textBox1.Focus(); textBox1.SelectAll(); SendKeys.Send("{BACKSPACE}"); 

Quelques faits partiellement pertinents – Dans WPF, quelle que soit la façon dont vous modifiez le texte, les méthodes Annuler et Répéter fonctionnent toujours correctement.

Voici une méthode peu rigoureuse, demandez à MS pourquoi ces méthodes ne sont pas publiques.

 public static class TextBoxUtils { // internal virtual void SetSelectedTextInternal(ssortingng text, bool clearUndo) private static readonly Action SetSelectedTextInternal = (Action)Delegate.CreateDelegate(typeof(Action), typeof(TextBox).GetMethod("SetSelectedTextInternal", BindingFlags.Instance | BindingFlags.NonPublic)); public static void UndoableClear(this TextBox target) { if (ssortingng.IsNullOrEmpty(target.Text)) return; target.SelectAll(); SetSelectedTextInternal(target, ssortingng.Empty, false); } } 

Usage

 myTextBox.UndoableClear(); 

Si vous n’aimez pas les hacks, vous pouvez utiliser P / Invoke et envoyer un message EM_REPLACESEL qui n’efface pas le tampon d’annulation interne de l’éditeur de texte tel que WM_SETTEXT .

J’ai trouvé cette question alors que je cherchais une solution dans VB.net. La solution de “hack” d’Ivan fonctionne très bien en VB.

En tant que vb.net:

 Module Module1 Private ReadOnly SetSelectedTextInternal As Action(Of TextBox, Ssortingng, Boolean) = DirectCast([Delegate].CreateDelegate(GetType(Action(Of TextBox, Ssortingng, Boolean)), GetType(TextBox).GetMethod("SetSelectedTextInternal", BindingFlags.Instance Or BindingFlags.NonPublic)), Action(Of TextBox, Ssortingng, Boolean))  Public Sub Delete(target As TextBox) If Ssortingng.IsNullOrEmpty(target.Text) Then Return 'target.SelectAll() SetSelectedTextInternal(target, Ssortingng.Empty, False) End Sub End Module