Отображение около мегабайта текста в WPF - PullRequest
1 голос
/ 07 февраля 2012

У меня есть пустое приложение WPF, которое отображает текст Meg ASCII. Я изначально поместил TextBlock в WrapPanel в ScrollViewer. Это правильно прокручивалось и изменял размер, когда я изменял размеры окна, но это было очень медленно! Мне нужно было что-то быстрее.

Таким образом, я поместил текст в FormattedText и обработал его, используя пользовательский элемент управления. Это было намного быстрее, но это не изменило размер. Так что я сделал свой пользовательский элемент управления размером. Но он будет перерисовывать слишком много раз в секунду, поэтому я сделал это только каждые 100 мс.

Намного лучше. Рендеринг и изменение размера всё ещё не велики, но намного лучше, чем были. Но я потерял прокрутку.

В конце концов мне нужно решение, которое делает многое, но сейчас я пытаюсь найти решение, которое делает немного: показать текст текста, обернуть, иметь полосу прокрутки и быть производительным. В конце концов, я бы хотел, чтобы он масштабировался до текста, имел встроенные цвета, некоторые события при наведении курсора / щелчке мышью для частей текста ...

Как сделать так, чтобы FormattedText (или, точнее, DrawingVisual) имел вертикальную полосу прокрутки?

Вот мой FrameworkElement, который показывает мой FormattedText:

using System;
using System.Windows;
using System.Windows.Media;

namespace Recall
{
    public class LightweightTextBox : FrameworkElement
    {
        private VisualCollection _children;
        private FormattedText _formattedText;
        private System.Threading.Timer _resizeTimer;
        private const int _resizeDelay = 100;

        public double MaxTextWidth
        {
            get { return this._formattedText.MaxTextWidth; }
            set { this._formattedText.MaxTextWidth = value; }
        }

        public LightweightTextBox(FormattedText formattedText)
        {
            this._children = new VisualCollection(this);
            this._formattedText = formattedText;

            DrawingVisual drawingVisual = new DrawingVisual();
            DrawingContext drawingContext = drawingVisual.RenderOpen();
            drawingContext.DrawText(this._formattedText, new Point(0, 0));
            drawingContext.Close();
            _children.Add(drawingVisual);

            this.SizeChanged += new SizeChangedEventHandler(LightweightTextBox_SizeChanged);
        }

        void LightweightTextBox_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.MaxTextWidth = e.NewSize.Width;

            if (_resizeTimer != null)
                _resizeTimer.Change(_resizeDelay, System.Threading.Timeout.Infinite);
            else
                _resizeTimer = new System.Threading.Timer(new System.Threading.TimerCallback(delegate(object state)
                {
                    ReDraw();
                    if (_resizeTimer == null) return;
                    _resizeTimer.Dispose();
                    _resizeTimer = null;
                }), null, _resizeDelay, System.Threading.Timeout.Infinite);
        }

        public void ReDraw()
        {
            this.Dispatcher.Invoke((Action)(() =>
                {
                    var dv = _children[0] as DrawingVisual;
                    DrawingContext drawingContext = dv.RenderOpen();
                    drawingContext.DrawText(this._formattedText, new Point(0, 0));
                    drawingContext.Close();
                }));
        }

        //===========================================================
        //Overrides

        protected override int VisualChildrenCount { get { return _children.Count; } }

        protected override Visual GetVisualChild(int index)
        {
            if (index < 0 || index >= _children.Count)
                throw new ArgumentOutOfRangeException();

            return _children[index];
        }
    }
}

1 Ответ

2 голосов
/ 07 февраля 2012

Для простого текста хорошо подходит только для чтения TextBox. Для более сложных задач вы можете использовать FlowDocuments (который может быть размещен в FlowDocumentScrollViewer), TextBlocks также размещать потоковое содержимое , но не предназначены для больших количеств.

1010 * MSDN *:

TextBlock не оптимизирован для сценариев, в которых требуется отображать более нескольких строк контента; для таких сценариев FlowDocument в сочетании с соответствующим управлением просмотра является лучшим выбором, чем TextBlock , с точки зрения производительности. После TextBlock , FlowDocumentScrollViewer является следующим легчайшим элементом управления для отображения содержимого потока и просто предоставляет область содержимого с прокруткой с минимальным пользовательским интерфейсом. FlowDocumentPageViewer оптимизирован для режима просмотра «страницы за раз» для потокового контента. Наконец, FlowDocumentReader поддерживает богатейший набор функций для просмотра потокового содержимого, но, соответственно, имеет больший вес.

...