SKowalsky
SKowalsky

Reputation: 7

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?

Upvotes: 0

Views: 1244

Answers (1)

Michael Puckett II
Michael Puckett II

Reputation: 6749

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.

Upvotes: 1

Related Questions