20

In a WPF application, I want to build a "Find in Files" output pane, in which I can stream large quantity of text, without re-allocating memory at each line, like the TextBox would do.

The WPF TextBox has a single Text property which stores a contiguous string. Each time, I want to add content, I need to do textBox.Text += "New Text", which is bad.

Ideally, that control would be virtual and require a minimum of resources, just for the visible lines.

I thought about using a standard ListBox with a VirtualizingStackPanel, but it does not allow Text Selection across lines.

(At each new line added, I want the control to update)

Any suggestion?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
decasteljau
  • 7,655
  • 10
  • 41
  • 58
  • Try a stack panel itself instead of the list box – Timothy Khouri Sep 11 '09 at 20:29
  • 1
    @Timothy -- how would that allow text selection across lines? – Drew Noakes Sep 11 '09 at 21:05
  • 5
    For people who came across this question because they were finding that a frequently changing (in my case read only) text box had the characteristics of a memory leak, be sure to set UndoLimit to something other than it's default of -1. The default value of -1 for a text box will allow unrestricted growth of undo history. – Derrick Nov 16 '11 at 22:53

4 Answers4

18

If you do not expect much more than ten-thousands of search results in your application, a TextBlock control or readonly multiline TextBox will suffice by far.

The TextBox class has an AppendText() method which should be fast enough for you.

If you need text highlighting / formatting then maybe you want to use RichTextBox.

codymanix
  • 28,510
  • 21
  • 92
  • 151
  • 1
    Thanks codymanix, the MSDN doc says: The AppendText method enables the user to append text to the contents of a text control without using text concatenation, which, can yield better performance when many concatenations are required. Also after looking at the implementation inside .NET Reflector, the AppendText is exactly what I need. – decasteljau Sep 12 '09 at 11:28
  • 2
    There is a performance issue with this solution. :( The TextBox takes too much UI resources (CPU) when flooding the control with thousands of lines. The TextBox is not virtual and does complex calculations at each AppentText() calls. I think we would need a control that does it's redraw & layout in a virtual manner, as the ItemsControl would do. – decasteljau Sep 14 '09 at 13:30
  • 10
    Keep in mind that the textbox could be storing each of your appends for undo operations. You might want to change the UndoLimit field on the textbox. – Kelly Jul 01 '10 at 16:10
7

If you have really large content, then unfortunately all the WPF textbox and similar controls are very slow. See this question. You could use AvalonEdit as a replacement.

Community
  • 1
  • 1
Daniel Rose
  • 17,233
  • 9
  • 65
  • 88
  • Wow, that's really a great suggestion. AvalonEdit's `TextEditor`solved my problems when trying to put more than 65k characters into a `TextBox` – j00hi Nov 27 '19 at 11:55
0

Have you considered or tried the RichTextBox control?

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • We have tried, but the performance become disastrous, probably because of the overkill related to string formatting, which I don't need. – decasteljau Sep 12 '09 at 11:17
-2

A StringBuilder, just append the text to the String builder and instead of doing

textBox.Text += moreText;

do

myStringBuilder.Append(moreText);
textBox.Text = myStringBuilder.ToString();

This should take care of the Schlemiel the Painter's algorithm.

Of course, the string builder should have to be a member of your class so it exists through your object's life span.

Carlo
  • 25,602
  • 32
  • 128
  • 176
  • each time you call ToString() on the StringBuilder, it allocates a new contiguous string containing the concatenated strings. Since I will be appending new lines to the control all the time, I exactly don't want that. For each new line, I want the control to update. – decasteljau Sep 12 '09 at 11:15