Rich
Rich

Reputation: 735

Poor TextBox performance with wrapping on and large amounts of data

I have a persistent problem with textboxes in WPF, using .NET 3.5. With a large (5000+ lines) amount of data in a TextBox with wrapping enabled, the window has ridiculously bad performance while being resized.

This only happens with TextWrapping="Wrap". Having the text data bound or just setting it programmatically makes no difference.

The code is literally as simple as this:

<TextBox Margin="12,39,337,29" Text="{Binding Output, Mode=OneWay}" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" />

The text is bound to a single string. The bound data is not being changed.

Edit: The data is not being changed while the window is resizing, is what I meant. It will be updated in the future. The TextBox does not need to be editable, but the actual text does need to be selectable. /Edit.

I've had a quick play with AvalonEdit, which has the same problem. It seems strange that I can't find any other threads which describe this issue.

Any advice?

Thanks, Rich

Upvotes: 3

Views: 3712

Answers (4)

00jt
00jt

Reputation: 3106

The part that is slow is displaying all that text at once. I have run into this issue before where the TextBox in my control became very large and had a ScrollViewer for the whole control that would handle the very large TextBox.

You are almost doing that, but without setting a max for your height/width, I'm not sure if your ScrollViewer is actually going to be utilized.

My solution is to use the built-in scrollViewer inside of your TextBox(which you are doing), and then limit the size of the textbox height/width so that it isn't trying to render 100% of the text all at once (and actually utilizes the ScrollViewer inside your TextBox)

(FYI, I also like using CanContentScroll=true, though I don't think it will affect the speed)

<TextBox Margin="12,39,337,29" TextWrapping="Wrap" 
         Text="{Binding Output, Mode=OneWay}"
         ScrollViewer.CanContentScroll="true"
         VerticalScrollBarVisibility="auto" 
         HorizontalScrollBarVisibility="auto" 
         MaxHeight="600" MaxWidth="600"/>

Upvotes: 3

chris
chris

Reputation: 403

You could react to the windowResizeStart event and disable wrapping for the text block. Then wrap just once when the resize completes.

You gain performance but lose some visual flair I guess.

Upvotes: 2

paparazzo
paparazzo

Reputation: 45096

If the text has line breaks then break it up into List string and then use a ListBox with TextBlock. If you need to edit then use TextBox. ListBox supports virtualiztion. So only the text displayed needs to be re sized.

This concatenates multiple empty lines to one. And has a non standard EOL.

bool lastNull = false;
string eol = ((char)174).ToString();
string[] docTextRaws = DocText.Split((char)174);
string docTextRaw;
for (Int32 j = 0; j < docTextRaws.Length; j++)
{
    docTextRaw = docTextRaws[j].TrimEnd();
    if (string.IsNullOrEmpty(docTextRaw))
    {
        if (!lastNull)
        {
            docTextDownloadLines.Add(eol);
            lastNull = true;
        }
    }
    else
    {
        docTextDownloadLines.Add(docTextRaw + eol);
        if (lastNull) lastNull = false;
    }
}

Upvotes: -1

Dean Chalk
Dean Chalk

Reputation: 20471

why not use a FlowDocumentScrollViewer instead of a TextBlock

http://msdn.microsoft.com/en-us/library/system.windows.controls.flowdocumentscrollviewer.aspx

Upvotes: 0

Related Questions