Search code examples
c#uwpconvertersuppercase

Force textbox to be uppercase in UWP (Windows 10)


I want to force the text a user inputs into a TextBox on a UWP app (for Windows 10) to be uppercase. WinForms and WPF both have a simple way to do this with the built in CharacterCasing, however UWP does not.

I tried two different methods; an online example by AlexDrenea, and I built a converter myself. In both situations, I found that when I typed "test" into the textbox, the text gets jumbled (for example, "test" appears as "TSTE").

I really thought the converter would work. Any suggestions on what can be done to improve it so it doesn't jumble up the letters?

XAML

<Page
    x:Class="MakeUppercaseEx2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MakeUppercaseEx2"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <local:TextToUppercaseConverter x:Name="MyUppercaseConverter" />
    </Page.Resources>

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBox Name="txtExample2" Margin="10" Text="{Binding ElementName=txtExample2, Path=Text, Converter={StaticResource MyUppercaseConverter}}" />
        <Button Name="btnDisplay" Margin="10" Content="Display" Click="btnDisplay_Click"/>
        <TextBlock Name="lblStatus" Margin="10" Text="" />
    </StackPanel>
</Page>

CodeBehind

using System;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace MakeUppercaseEx2
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void btnDisplay_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) {
            lblStatus.Text = "You entered: " + txtExample2.Text;
        }
    }

    public class TextToUppercaseConverter : IValueConverter {
        public object Convert(object value, Type targetType, object parameter, string language) {
            string sTypedValue = System.Convert.ToString(value);
            if (string.IsNullOrEmpty(sTypedValue)) {
                return "";
            }
            return sTypedValue.ToUpper();
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language) {
            throw new NotImplementedException();
        }
    }
}

Solution

  • Here's how I would do it.

    I will create a TemplatedControl that is inherited from TextBox and will manage TextChanged events inside the TemplatedControl so that it can be used anywhere. Also I would make a Property that determines if i want text capitalized always or not. That way i can use the same control in all places necessary.

    Below is a simple TextBox Inherited TemplatedControl

    public sealed class MyTextBox : TextBox
    {
        public MyTextBox()
        {
            this.DefaultStyleKey = typeof(TextBox);
        }
    
        public CaseType CharacterCasing
        {
            get { return (CaseType)GetValue(CharacterCasingProperty); }
            set { SetValue(CharacterCasingProperty, value); }
        }
    
        public static readonly DependencyProperty CharacterCasingProperty = DependencyProperty.Register("CharacterCasing", typeof(CaseType), typeof(MyTextBox), new PropertyMetadata(CaseType.Normal,(s,e)=>
        {
            TextBox myTextBox = (TextBox)s;
            if ((CaseType)e.NewValue !=(CaseType)e.OldValue)
            {
                myTextBox.TextChanged += MyTextBox_TextChanged;
            }
            else
            {
                myTextBox.TextChanged -= MyTextBox_TextChanged;
            }
        }));
    
        private static void MyTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            MyTextBox myTextBox = sender as MyTextBox;
            switch(myTextBox.CharacterCasing)
            {
                case CaseType.UpperCase:
                    myTextBox.Text = myTextBox.Text.ToUpper();
                    break;
                case CaseType.LowerCase:
                    myTextBox.Text = myTextBox.Text.ToLower();
                    break;
                default:
                    break;
            }
            myTextBox.SelectionStart = myTextBox.Text.Length;
        }
    
        public enum CaseType
        {
            Normal,
            UpperCase,
            LowerCase
        }
    }
    

    I created a Enum called CaseType that will determine what case the TextBox should respect when user is typing the text.

    and in the TextChanged event, i am CaseConverting the text based on Enum.

    You can use this in XAML like below.

    <local:MyTextBox HorizontalAlignment="Center"
                     VerticalAlignment="Center"
                     CharacterCasing="UpperCase"/>
    

    You can expand the control with more options for CaseConverting as per your requirement.

    Good Luck.


    Update

    Here is a Github Repo. Feel free to download and compare with what you are doing.