Browse Source

Merge pull request #788 from AvaloniaUI/fixes/728-textbox-invalid-caretindex

Coerce TextBox.CaretIndex when setting Text.
Steven Kirk 9 years ago
parent
commit
53b76fb5f7

+ 4 - 2
src/Avalonia.Controls/TextBox.cs

@@ -202,6 +202,7 @@ namespace Avalonia.Controls
             {
                 if (!_ignoreTextChanges)
                 {
+                    CaretIndex = CoerceCaretIndex(CaretIndex, value?.Length ?? 0);
                     SetAndRaise(TextProperty, ref _text, value);
                 }
             }
@@ -558,10 +559,11 @@ namespace Avalonia.Controls
             return null;
         }
 
-        private int CoerceCaretIndex(int value)
+        private int CoerceCaretIndex(int value) => CoerceCaretIndex(value, Text?.Length ?? 0);
+
+        private int CoerceCaretIndex(int value, int length)
         {
             var text = Text;
-            var length = text?.Length ?? 0;
 
             if (value < 0)
             {

+ 29 - 0
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@@ -1,6 +1,8 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
+using System;
+using System.Reactive.Linq;
 using Avalonia.Controls.Presenters;
 using Avalonia.Controls.Templates;
 using Avalonia.Data;
@@ -200,6 +202,33 @@ namespace Avalonia.Controls.UnitTests
             }
         }
 
+        [Fact]
+        public void Setting_Text_Updates_CaretPosition()
+        {
+            using (UnitTestApplication.Start(Services))
+            {
+                var target = new TextBox
+                {
+                    Text = "Initial Text",
+                    CaretIndex = 11
+                };
+
+                var invoked = false;
+
+                target.GetObservable(TextBox.TextProperty).Skip(1).Subscribe(_ =>
+                {
+                    // Caret index should be set before Text changed notification, as we don't want
+                    // to notify with an invalid CaretIndex.
+                    Assert.Equal(7, target.CaretIndex);
+                    invoked = true;
+                });
+
+                target.Text = "Changed";
+
+                Assert.True(invoked);
+            }
+        }
+
         private static TestServices Services => TestServices.MockThreadingInterface.With(
             standardCursorFactory: Mock.Of<IStandardCursorFactory>());