How can I undo a TextBox's text changes caused by a binding?
Solution 1
OK, started to leave a comment and realized it was an answer :)
TextBox.Undo() is intended to undo a user's interaction with the text box not a value change in the property it's bound to. A change in the property the text box is bound to will just update the value of the TextBox, this is a different change than a user edit via focus/keyboard. If you need to Undo changes to your bound properties you probably need to investigate adding an Undo/Redo stack to your application.
Solution 2
I was facing the same issue (needed to accept input upon Enter and revert to original value upon Escape) and was able to handle it this way:
- Set
UpdateSourceTrigger
of yourTextBox.Text
binding toExplicit
. Handle
KeyDown
event of your TextBox and put the following code in there:if (e.Key == Key.Enter || e.Key == Key.Escape) { BindingExpression be = ((TextBox)sender).GetBindingExpression(TextBox.TextProperty); if (e.Key == Key.Enter) { if (be != null) be.UpdateSource(); } else if (e.Key == Key.Escape) { if (be != null) be.UpdateTarget(); //cancels newly supplied value and reverts to the original value } }
I found this solution to be very elegant because it can be used in DataTemplates too. For example in my case I used it to allow in-place editing of ListBox items.
Solution 3
Assign directly to the TextBox:
textBox.SelectAll();
textBox.SelectedText = newText;
Solution 4
The TextBox will apply the changes to the internal undo stack if they are applied in such a way that they appear to have come from the user, like so:
Clipboard.SetText("NewTextHere");
TextBox.Paste();
It's a terrible workaround, as it kills whatever the user has on the clipboard (the restoring of which is pessimistically discussed here: How do I backup and restore the system clipboard in C#?) but I thought it might be worth having posted nonetheless.
Comments
-
H.B. over 1 year
I have a
TextBox
to which i bound a string, if i now edit the text manually i will be able to undo those changes viaTextBox.Undo()
, if however i change the string and the TextBox's text is updated, i cannot undo those changes and theTextBox.CanUndo
property will always befalse
.
I suppose this might have to do with the complete replacement of the text rather than a modification of it.Any ideas on how i can get this to work?
-
Paul Wheeler over 13 yearsHave you tried Mode=TwoWay in your binding string?
-
Paul Wheeler over 13 yearsNever mind, TwoWay binding didn't work...
-
-
H.B. over 13 yearsI suspected that there would not be a simple solution, then again, it was not really a good idea to try and handle undoing by reverting a change that occurred in a control, rather than the model. Thanks.
-
H.B. almost 13 yearsI think you misunderstood the question, this is about the undo functionality, i know how to overwrite existing text. There is no
newText
, i was trying to restore an old value that should have been stored in the TextBox's history. -
H.B. over 12 yearsAn interesting idea at the very least. Thanks for your contribution.
-
Darkhydro about 10 years@H.B. This works great! Doesn't overwrite the clipboard, and allows you to undo text assignments that weren't made by the user! Thanks Pixar! H.B. I would consider rewarding Pixar with the answer, since this does exactly what you asked for in the question.
-
H.B. about 10 years@Darkhydro: No, unfortunately the question is about text changes caused by bindings, i.e. the property that the
TextBox.Text
is bound to is changed, no interaction with theTextBox
itself. -
Mike Marynowski over 7 yearsThis can be easily expanded to do what you want with an attached property, so you can do something like
UserText.Value="{Binding Xyz}"
which updates the text using the method in this answer when it changes instead of using the Text property directly. I know this answer is old, but might be of interest to someone coming by it now. -
H.B. over 7 yearsThis does not cover the case where immediate value propagation is desired. You probably would want to save on lost focus as well. Still, it might be a decent work around in some cases.