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
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.
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"/>
why not use a FlowDocumentScrollViewer
instead of a TextBlock
http://msdn.microsoft.com/en-us/library/system.windows.controls.flowdocumentscrollviewer.aspx
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;
}
}