Unplanned
Last Updated: 19 May 2026 13:02 by ADMIN
Teddy
Created on: 19 May 2026 11:56
Category: Entry
Type: Bug Report
1
AutoComplete: [WinUI] [MacCatalyst] Cursor position changes to end when trying to edit text in different location than end and using TextTransform Uppercase
When using the Telerik RadTextInput control with TextTransform="Uppercase", if you edit text in the middle of the input (e.g., change "MSFT" to "MEFT" by replacing "S" with "E") while caps lock is OFF, the cursor jumps to the end of the text after typing. However, if caps lock is ON, the cursor remains in the correct position after editing.
1 comment
ADMIN
Didi
Posted on: 19 May 2026 13:02

Workaround:

Find the inner control RadTextInput and update the cursor position using the TextChanged and TextChanging events:

public partial class MainPage : ContentPage
{
    private int _previousCursorPosition = 0;
    private int _previousTextLength = 0;
    private RadTextInput _autoCompleteTextInput;

    public MainPage()
    {
        InitializeComponent();
        // Wait for the control to load and then find the internal RadTextInput
        autoComplete.Loaded += AutoComplete_Loaded;
    }

    private void AutoComplete_Loaded(object sender, EventArgs e)
    {
        // Find the internal RadTextInput in the RadAutoComplete
        _autoCompleteTextInput = FindRadTextInputInVisualTree(autoComplete);

        if (_autoCompleteTextInput != null)
        {
            _autoCompleteTextInput.TextChanging += RadTextInput_TextChanging;
            _autoCompleteTextInput.TextChanged += RadTextInput_TextChanged;
        }
    }

    private RadTextInput FindRadTextInputInVisualTree(Element element)
    {
        if (element is RadTextInput textInput)
        {
            return textInput;
        }
        if (element is Layout layout)
        {
            foreach (var child in layout.Children)
            {
                var result = FindRadTextInputInVisualTree(child as Element);
                if (result != null)
                {
                    return result;
                }
            }
        }
        else if (element is ContentView contentView && contentView.Content != null)
        {
            return FindRadTextInputInVisualTree(contentView.Content as Element);
        }
        else if (element is ScrollView scrollView && scrollView.Content != null)
        {
            return FindRadTextInputInVisualTree(scrollView.Content as Element);
        }
        else if (element is ContentPage page && page.Content != null)
        {
            return FindRadTextInputInVisualTree(page.Content as Element);
        }

        var type = element.GetType();
        var childrenProperty = type.GetProperty("Children");
        var contentProperty = type.GetProperty("Content");

        if (childrenProperty != null)
        {
            var children = childrenProperty.GetValue(element);
            if (children is System.Collections.IEnumerable enumerable)
            {
                foreach (var child in enumerable)
                {
                    if (child is Element childElement)
                    {
                        var result = FindRadTextInputInVisualTree(childElement);
                        if (result != null)
                        {
                            return result;
                        }
                    }
                }
            }
        }
        else if (contentProperty != null)
        {
            var content = contentProperty.GetValue(element);
            if (content is Element contentElement)
            {
                return FindRadTextInputInVisualTree(contentElement);
            }
        }

        return null;
    }

    private void RadTextInput_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (sender is RadTextInput textInput)
        {
            int newTextLength = e.NewTextValue?.Length ?? 0;
            int oldTextLength = e.OldTextValue?.Length ?? 0;
            int lengthDifference = newTextLength - oldTextLength;
            int expectedCursorPosition = _previousCursorPosition + lengthDifference;
            expectedCursorPosition = Math.Max(0, Math.Min(expectedCursorPosition, newTextLength));

            Dispatcher.Dispatch(() =>
            {
                textInput.CursorPosition = expectedCursorPosition;
            });

            _previousCursorPosition = expectedCursorPosition;
            _previousTextLength = newTextLength;
        }
    }

    private void RadTextInput_TextChanging(object sender, TextChangingEventArgs e)
    {
        if (sender is RadTextInput textInput)
        {
            _previousCursorPosition = textInput.CursorPosition;
            _previousTextLength = textInput.Text?.Length ?? 0;
        }
    }
}

Regards,
Didi
Progress Telerik