Search code examples
c#wpfwindowsuwptextbox

WPF Textbox Element freezes when setting the text property to a large string


I am currently developing an UWP app and I encountered a problem with the TextBox WPF Element, which seems to have terrible performance when dealing with larger texts. Pasting a large text from the clipboard into the textbox works perfectly fine, but when I try to set the text programmatically it freezes the entire application:

textbox.Text = sb.ToString(); //Freezes or takes for ever

This is how I defined the textbox in my MainPage.xaml:

<TextBox x:Name="textbox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" Margin="0,0,0,70"/>

Does anyone know of a solution to this performance problem or are there any alternative text field elements I could use?


Solution

  • Ok... I've been able to get the time it takes to add the text to take up to 133 milliseconds is the highest I found. That's a slight jitter; if I add 50K characters it takes about 1000ms which is noticeable but not that bad given the number of characters.

    To perform the test I first made a view with: ProgressBar to detect UI freezing / jitter. TextBlock to show time in milliseconds it takes to add the text. Button to start the adding of the text. TextBox to add the text to.

    MainPage.xaml

    <Page x:Class="Question_Answer_UWPApp.MainPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          mc:Ignorable="d">
    
        <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    
            <ProgressBar Name="progressBarAddingText"
                         IsIndeterminate="True" />
    
            <TextBlock Name="textBlockAddingTextTime" />
    
            <Button Content="Add Text"
                    Click="ButtonClick" />
    
            <TextBox Name="textBoxAddingText"
                     HorizontalAlignment="Stretch"
                     VerticalAlignment="Stretch"
                     ScrollViewer.VerticalScrollBarVisibility="Auto"
                     TextWrapping="Wrap"
                     Margin="0,0,0,70" />
    
        </StackPanel>
    </Page>
    

    MainPage.xaml.cs

    using System.Diagnostics;
    using System.Text;
    using System.Threading.Tasks;
    using Windows.UI.Xaml.Controls;
    
    namespace Question_Answer_UWPApp
    {
        public sealed partial class MainPage : Page
        {
            public static Stopwatch stopwatch = new Stopwatch();
            public MainPage()
            {
                InitializeComponent();
            }
    
            public async void AddTextAsynchronously()
            { 
                var text = await Task.Run(() =>
                {
                    var stringBuilder = new StringBuilder();
    
                    for (int i = 0; i < 5000; i++)
                        stringBuilder.Append("X");
    
                    return stringBuilder.ToString();
                });
    
                stopwatch.Start();
    
                textBoxAddingText.Text = text;
    
                stopwatch.Stop();
                textBlockAddingTextTime.Text = $"{stopwatch.ElapsedMilliseconds.ToString()} milliseconds";
            }
    
            private void ButtonClick(object sender, Windows.UI.Xaml.RoutedEventArgs e)
            {
                AddTextAsynchronously();
            }
        }
    }
    

    In this test I got about 133ms but when I place the StringBuilder outside of the Task and use the Task just to build the StringBuilder (essentially allowing me to say .Text = stringBuilder.ToString() it takes about another 10 milliseconds. Which means the StringBuilder isn't the bottle neck. I don't believe the adding of the text to the TextBox is your bottleneck either.

    With this test I feel that you should look in other locations for your bottleneck. This should safely answer the question that adding text to the TextBox via code isn't time consuming.