1

We are developing a .Net 4.0 C# WPF Line-of-business app and need to show (readonly) large text files to the user. TextBlock as stated in SO is not an option and tried the suggested AvalonEdit control. Running the AvalonEdit.Sample standalone app can load a 4MB file with 8k lines in less than a second, but when embedding the AvalonEdit TextEditor into our WPF app spends 20 seconds, almost the same as the previous TextBlock.

The UI is quite complex, with a splitter for tree-menu and forms. The form has several splitters to create resizable zones and one of them contains a tab control. One of the tab items has the TextEditor from AvalonEdit.

XAML

<avalonEdit:TextEditor Name="Tbx" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" />

CS

public void ShowFile(string path)
{
  Tbx.Text = string.Empty;
  ThreadPool.QueueUserWorkItem(o => {
      var lines = File.ReadAllLines(path).Join("\n");
      Dispatcher.BeginInvoke(() => Tbx.Text = lineas);
  });
}

When loading the file, my laptop i7 4-core CPU usage is 33%.

Any suggestion about the different behaviour of AvalonEdit TextEditor as standalone app and within a custom WPF app?

How to load large files (10MB, 10k lines) with TextEditor?

UPDATE:

The Visual Tree:

Visual tree

The properties of the TextEditor:

TextEditor properties

I removed a ScrollViewer that host the TextEditor as pointed, but same poor performance is achieved.

UPDATE 2: I moved the TextEditor to a new window to reduce the layout but still get poor performance.

The new, simplified Visual Tree:

Visual Tree 2

Grid column and row definition is *.

The properties of the TextEditor:

TextEditor properties

David Oliván
  • 2,717
  • 1
  • 19
  • 26

3 Answers3

4

Look at the visual tree of your application (Snoop may help) and see if there is any ScrollViewer around the TextEditor control.

Scroll viewers give infinite space to the contained control, which will disable any UI virtualization and destroy performance (the editor needs to render the whole document, not just the visible portion).

If you need the nested scroll viewers for some reason, take a look my answer on the Nested Scroll Areas question to see how to avoid giving the contained control infinite space.

Community
  • 1
  • 1
Daniel
  • 15,944
  • 2
  • 54
  • 60
3

I found that virtualization is not performed horizontally. In my case I had a large XML file with no newlines so massive horizontal scrolling and took 10 seconds+ to render. Once the same text was formatted (with newlines) then it renders sub-second.

Co-der
  • 363
  • 1
  • 14
0

The TextDocument class has a function called SetOwnerThread(), from the doc, it seems you can temporarily set different thread for loading and rendering doc.

Below is from the comment of TextDocument.cs

    /// <summary>
    /// Transfers ownership of the document to another thread. This method can be used to load
    /// a file into a TextDocument on a background thread and then transfer ownership to the UI thread
    /// for displaying the document.
    /// </summary>
    /// <remarks>
    /// The owner can be set to null, which means that no thread can access the document. But, if the document
    /// has no owner thread, any thread may take ownership by calling SetOwnerThread.
    /// </remarks>
David
  • 15,894
  • 22
  • 55
  • 66
  • 2
    `SetOwnerThread()` is intended so that you can create+load a `TextDocument` on a background thread; but that doesn't help when the rendering is slow. Loading the text into the document usually is fast enough so that it isn't worth doing it on a background thread. – Daniel Mar 19 '13 at 17:18