Avalonia
Avalonia copied to clipboard
Support ChacaracterCasing in TextBox
Is your feature request related to a problem? Please describe. Fix character casing on TextBoxes.
ALL FRAMEWORKS have it. (WInUI / UWP / WPF / WinForms)
Describe the solution you'd like
control how characters are cased when they are manually entered into the text box.
Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.
Additional context
basicaly:
Add an enum
**public enum CharacterCasing
{
Normal = 0,
Upper,
Lower
}**
modify textbox.cs
**public static readonly StyledProperty<CharacterCasing> CharacterCasingProperty =
AvaloniaProperty.Register<TextBox, CharacterCasing>(nameof(CharacterCasing));**
**private string? AdjustCasing(string? text)
{
return CharacterCasing switch
{
CharacterCasing.Lower => text?.ToLower(),
CharacterCasing.Upper => text?.ToUpper(),
CharacterCasing.Normal => text,
_ => text
};
}**
**public CharacterCasing CharacterCasing
{
get => GetValue(CharacterCasingProperty);
set => SetValue(CharacterCasingProperty, value);
}**
/// <summary>
/// Gets or sets the Text content of the TextBox
/// </summary>
**[Content]
public string? Text
{
get => AdjustCasing(GetValue(TextProperty));
set => SetValue(TextProperty, AdjustCasing (value));
}**
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == TextProperty)
{
CoerceValue(CaretIndexProperty);
CoerceValue(SelectionStartProperty);
CoerceValue(SelectionEndProperty);
RaiseTextChangeEvents();
UpdatePseudoclasses();
UpdateCommandStates();
}
**else if (change.Property == CharacterCasingProperty)
{
Text = AdjustCasing(Text);
}**
else if (change.Property == CaretIndexProperty)
{
OnCaretIndexChanged(change);
}
else if (change.Property == SelectionStartProperty)
{
OnSelectionStartChanged(change);
}
else if (change.Property == SelectionEndProperty)
{
OnSelectionEndChanged(change);
}
else if (change.Property == MaxLinesProperty)
{
InvalidateMeasure();
}
else if (change.Property == UndoLimitProperty)
{
OnUndoLimitChanged(change.GetNewValue<int>());
}
else if (change.Property == IsUndoEnabledProperty && change.GetNewValue<bool>() == false)
{
// from docs at
// https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.textboxbase.isundoenabled:
// "Setting this property to false clears the undo stack.
// Therefore, if you disable undo and then re-enable it, undo commands still do not work
// because the undo stack was emptied when you disabled undo."
_undoRedoHelper.Clear();
_selectedTextChangesMadeSinceLastUndoSnapshot = 0;
_hasDoneSnapshotOnce = false;
}
}
private void HandleTextInput(string? input)
{
if (IsReadOnly)
{
return;
}
**input = AdjustCasing(RemoveInvalidCharacters(input));**
if (string.IsNullOrEmpty(input))
{
return;
}
_selectedTextChangesMadeSinceLastUndoSnapshot++;
SnapshotUndoRedo(ignoreChangeCount: false);
var currentText = Text ?? string.Empty;
var selectionLength = Math.Abs(SelectionStart - SelectionEnd);
var newLength = input.Length + currentText.Length - selectionLength;
if (MaxLength > 0 && newLength > MaxLength)
{
input = input.Remove(Math.Max(0, input.Length - (newLength - MaxLength)));
newLength = MaxLength;
}
if (!string.IsNullOrEmpty(input))
{
var textBuilder = StringBuilderCache.Acquire(Math.Max(currentText.Length, newLength));
textBuilder.Append(currentText);
var caretIndex = CaretIndex;
if (selectionLength != 0)
{
var (start, _) = GetSelectionRange();
textBuilder.Remove(start, selectionLength);
caretIndex = start;
}
textBuilder.Insert(caretIndex, input);
SetCurrentValue(TextProperty, StringBuilderCache.GetStringAndRelease(textBuilder));
ClearSelection();
if (IsUndoEnabled)
{
_undoRedoHelper.DiscardRedo();
}
SetCurrentValue(CaretIndexProperty, caretIndex + input.Length);
}
}