我試圖在WPF RichTextBox中顯示基本的語法高亮顯示。它主要工作,但渲染性能很糟糕。WPF:將格式應用到RichTextBox的快速方法
首先,我天真地試着:
/// <summary>
/// Main event handler for syntax highlighting.
/// </summary>
private void XmlChanged(object sender, TextChangedEventArgs e)
{
VM.Dirty = true;
if (VM.Pretty)
{
var range = new TextRange(XmlView.Document.ContentStart, XmlView.Document.ContentEnd);
Render(range.Text);
}
}
/// <summary>
/// Entry point for programmatically resetting the textbox contents
/// </summary>
private void Render(string text)
{
XmlView.TextChanged -= this.XmlChanged;
if (VM.Pretty)
{
var tokens = tokenizer.Tokenize(text);
Format(XmlView.Document, tokens);
}
XmlView.TextChanged += this.XmlChanged;
}
private void Format(FlowDocument doc, List<Token> tokens)
{
var start = doc.ContentStart;
foreach (var token in tokens)
{
TextRange range = new TextRange(start.GetPositionAtOffset(token.StartPosition, LogicalDirection.Forward),
start.GetPositionAtOffset(token.EndPosition, LogicalDirection.Forward));
range.ApplyPropertyValue(TextElement.ForegroundProperty, m_syntaxColors[token.Type]);
}
}
測試與剛剛超過100個令牌的2KB文件,花了1-2秒後,每個按鍵重繪;顯然不能接受。分析表明我的標記器比Format()函數快幾個數量級。於是,我嘗試了一些雙緩衝:
private void Render(string text)
{
XmlView.TextChanged -= this.XmlChanged;
// create new doc offscreen
var doc = new FlowDocument();
var range = new TextRange(doc.ContentStart, doc.ContentEnd);
range.Text = text;
if (VM.Pretty)
{
var tokens = tokenizer.Tokenize(text);
Format(doc, tokens);
}
// copy to active buffer
var stream = new MemoryStream(65536);
range.Save(stream, DataFormats.XamlPackage);
var activeRange = new TextRange(XmlView.Document.ContentStart, XmlView.Document.ContentEnd);
activeRange.Load(stream, DataFormats.XamlPackage);
XmlView.TextChanged += this.XmlChanged;
}
基準測試表明格式()運行速度稍快渲染屏幕外,但感知性能是現在更慘!
什麼是正確的方式去做這件事?
Hi Richard, 您是否曾經爲此解決過問題?我遇到類似WPF RichTextBox的問題。 祝好, Alan – 2010-07-09 09:04:51
我的第三次嘗試是這樣的:(1)創建一個長時間運行的後臺線程,在按鍵時管理它自己的文檔(2)的XAML表示,發佈到另一個線程觀看(3)出列,手動操作XAML文檔(即使用字符串解析,而不是FlowDocument)(4),每當你遇到一個好的停止點時,將修訂後的XAML發回UI線程並執行TextRange.Load()。這表現好得多,但仍然不是很好。如果我仍然關心這個項目,我會在Reflector中查看它是如何執行的:) – 2010-07-10 04:50:59