From 01c50a8727e6a4b7e32d64fcf2f2c7865a0cd07d Mon Sep 17 00:00:00 2001 From: Curtis Wensley Date: Tue, 10 Dec 2024 16:46:12 -0800 Subject: [PATCH] Wpf: Fix TextBox.Text so it clears the undo buffer when set --- src/Eto.Wpf/Forms/Controls/TextBoxHandler.cs | 76 +++++++++---------- .../UnitTests/Forms/Controls/TextBoxTests.cs | 28 +++++++ 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/src/Eto.Wpf/Forms/Controls/TextBoxHandler.cs b/src/Eto.Wpf/Forms/Controls/TextBoxHandler.cs index c504a1acfb..aa3a6602be 100755 --- a/src/Eto.Wpf/Forms/Controls/TextBoxHandler.cs +++ b/src/Eto.Wpf/Forms/Controls/TextBoxHandler.cs @@ -298,55 +298,53 @@ public string Text var oldText = Text; CurrentText = null; var newText = value ?? string.Empty; - TextBox.BeginChange(); - if (newText != oldText) - { - var args = new TextChangingEventArgs(oldText, newText, false); - Callback.OnTextChanging(Widget, args); - if (args.Cancel) - { - TextBox.EndChange(); - return; - } + if (newText == oldText) + return; - var needsTextChanged = TextBox.Text == newText; + var args = new TextChangingEventArgs(oldText, newText, false); + Callback.OnTextChanging(Widget, args); + if (args.Cancel) + return; - // Improve performance when setting text often - // See https://github.com/dotnet/wpf/issues/5887#issuecomment-1604577981 - var endNoGCRegion = EnableNoGCRegion - && GCSettings.LatencyMode != GCLatencyMode.NoGCRegion; + var needsTextChanged = TextBox.Text == newText; - try - { - endNoGCRegion &= GC.TryStartNoGCRegion(1000000); // is this magic number reasonable?? - } - catch - { - // Ignore any exceptions, they can apparently still happen even though we check the LatencyMode above - endNoGCRegion = false; - } + // Improve performance when setting text often + // See https://github.com/dotnet/wpf/issues/5887#issuecomment-1604577981 + var endNoGCRegion = EnableNoGCRegion + && GCSettings.LatencyMode != GCLatencyMode.NoGCRegion; - try - { - TextBox.Text = newText; - } - finally - { - if (endNoGCRegion && GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) - GC.EndNoGCRegion(); - } - - if (needsTextChanged) - { - Callback.OnTextChanged(Widget, EventArgs.Empty); - } + try + { + endNoGCRegion &= GC.TryStartNoGCRegion(1000000); // is this magic number reasonable?? } + catch + { + // Ignore any exceptions, they can apparently still happen even though we check the LatencyMode above + endNoGCRegion = false; + } + + try + { + TextBox.Text = newText; + } + finally + { + if (endNoGCRegion && GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) + GC.EndNoGCRegion(); + } + if (value != null && AutoSelectMode == AutoSelectMode.Never && !HasFocus) { + TextBox.BeginChange(); TextBox.SelectionStart = value.Length; TextBox.SelectionLength = 0; + TextBox.EndChange(); + } + + if (needsTextChanged) + { + Callback.OnTextChanged(Widget, EventArgs.Empty); } - TextBox.EndChange(); } } diff --git a/test/Eto.Test/UnitTests/Forms/Controls/TextBoxTests.cs b/test/Eto.Test/UnitTests/Forms/Controls/TextBoxTests.cs index 6b6f0373a9..9266353723 100644 --- a/test/Eto.Test/UnitTests/Forms/Controls/TextBoxTests.cs +++ b/test/Eto.Test/UnitTests/Forms/Controls/TextBoxTests.cs @@ -6,6 +6,34 @@ namespace Eto.Test.UnitTests.Forms.Controls public abstract class TextBoxBase : TestBase where T: TextBox, new() { + [Test, ManualTest] + public void SettingTextShouldClearUndoBuffer() + { + ManualForm("Try typing and undo/redo, then press the button to reset. After reset, it should not undo to previous values", form => + { + var textBox = new T(); + textBox.Text = "Hello"; + textBox.SelectAll(); + + var button = new Button { Text = "Click Me" }; + button.Click += (sender, e) => + { + textBox.Text = "Thanks, now try to undo"; + textBox.Focus(); + }; + + return new TableLayout + { + Spacing = new Size(5, 5), + Padding = 10, + Rows = { + textBox, + button + } + }; + }); + } + [Test, ManualTest] public void CaretIndexShouldStartInInitialPosition() {