У меня есть пустое приложение 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];
}
}
}