diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index 346e561dfc..5c885ad091 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -96,6 +96,12 @@
+
+
+
+
+
+
+ /// Defines how text is cased.
+ ///
+ public enum CharacterCasing
+ {
+ ///
+ /// The text casing is normal.
+ ///
+ Normal,
+
+ ///
+ /// The text casing is upper.
+ ///
+ Upper,
+
+ ///
+ /// The text casing is lower.
+ ///
+ Lower
+ }
+}
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index eadb54b58a..7a93a813bc 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -159,6 +159,9 @@ namespace Avalonia.Controls
public static readonly StyledProperty TextAlignmentProperty =
TextBlock.TextAlignmentProperty.AddOwner();
+ public static readonly StyledProperty CharacterCasingProperty =
+ AvaloniaProperty.Register(nameof(CharacterCasing), defaultValue: CharacterCasing.Normal);
+
///
/// Defines the property.
///
@@ -455,6 +458,14 @@ namespace Avalonia.Controls
set => SetValue(CaretIndexProperty, value);
}
+ private void OnCharacterCasingChanged(AvaloniaPropertyChangedEventArgs e)
+ {
+ var tb = (TextBox)e.Sender;
+ var newValue = AdjustCasing(tb.Text, e.GetNewValue());
+
+ SetCurrentValue(TextProperty, newValue);
+ }
+
private void OnCaretIndexChanged(AvaloniaPropertyChangedEventArgs e)
{
UndoRedoState state;
@@ -638,8 +649,8 @@ namespace Avalonia.Controls
{
SnapshotUndoRedo();
}
-
- return value;
+
+ return AdjustCasing(value, textBox.CharacterCasing);
}
///
@@ -691,6 +702,15 @@ namespace Avalonia.Controls
set => SetValue(TextAlignmentProperty, value);
}
+ ///
+ /// Gets or sets the of the TextBox.
+ ///
+ public CharacterCasing CharacterCasing
+ {
+ get => GetValue(CharacterCasingProperty);
+ set => SetValue(CharacterCasingProperty, value);
+ }
+
///
/// Gets or sets the placeholder or descriptive text that is displayed even if the
/// property is not yet set.
@@ -1036,12 +1056,15 @@ namespace Avalonia.Controls
CoerceValue(CaretIndexProperty);
CoerceValue(SelectionStartProperty);
CoerceValue(SelectionEndProperty);
-
RaiseTextChangeEvents();
UpdatePseudoclasses();
UpdateCommandStates();
}
+ else if (change.Property == CharacterCasingProperty)
+ {
+ OnCharacterCasingChanged(change);
+ }
else if (change.Property == CaretIndexProperty)
{
OnCaretIndexChanged(change);
@@ -1158,6 +1181,7 @@ namespace Avalonia.Controls
}
input = SanitizeInputText(input);
+ input = AdjustCasing(input, CharacterCasing);
if (string.IsNullOrEmpty(input))
{
@@ -2272,6 +2296,20 @@ namespace Avalonia.Controls
return text.Substring(start, end - start);
}
+ ///
+ /// Adjust the text casing.
+ ///
+ /// The text to adjust.
+ /// The character casing we want.
+ ///
+ private static string? AdjustCasing(string? text, CharacterCasing characterCasing) => characterCasing switch
+ {
+ CharacterCasing.Lower => text?.ToLower(System.Globalization.CultureInfo.CurrentCulture),
+ CharacterCasing.Upper => text?.ToUpper(System.Globalization.CultureInfo.CurrentCulture),
+ CharacterCasing.Normal => text,
+ _ => text
+ };
+
///
/// Returns the sum of any vertical whitespace added between the and in the control template.
///
diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
index fa578a7afe..a83b2c8b61 100644
--- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
@@ -1517,6 +1517,37 @@ namespace Avalonia.Controls.UnitTests
}
}
+ [Theory]
+ [InlineData(CharacterCasing.Lower, "LoWer", "lower")]
+ [InlineData(CharacterCasing.Upper, "uppEr", "UPPER")]
+ [InlineData(CharacterCasing.Normal, "NorMal", "NorMal")]
+ public void Should_Respect_Casing(CharacterCasing casing, string value, string expected)
+ {
+ var target = new TextBox
+ {
+ Template = CreateTemplate(),
+ CharacterCasing = casing,
+ Text = value
+ };
+
+ Assert.Equal(target.Text, expected);
+ }
+
+ [Fact]
+ public void Should_Update_Casing_After_First_Render()
+ {
+ var tb = new TextBox
+ {
+ Template = CreateTemplate(),
+ Text = "abc"
+ };
+
+ tb.Measure(Size.Infinity);
+ tb.CharacterCasing = CharacterCasing.Upper;
+
+ Assert.Equal("ABC", tb.Text);
+ }
+
[Fact]
public void Should_Move_Caret_To_EndOfLine()
{