簡體   English   中英

WPF Textblock性能差

[英]WPF Textblock Performance Poor

在顯示甚至少量數據時,我一直遇到WPF DataGrid和列表框GridView性能問題。 我雖然這個問題只是WPF一般表現不佳,但問題似乎只在於文本塊控件。

我創建了一個示例面板,我添加了幾個項目。 如果我添加簡單填充的矩形,調整大小/滾動性能是完美的,但是一旦我使用了文本塊,性能就會消失。

看起來性能問題來自於:

child.Measure(constraint); 

當測量文本塊時,它會使性能停止。 有什么我可以覆蓋文本塊的測量或某些東西來提高性能嗎? (我會明確設置孩子的大小)

編輯:我現在已經創建了簡化的代碼來安排我想要的項目。

此代碼的性能很好,除了...當文本塊內的文本寬度超過文本塊的實際寬度時。 這使我的表現回歸到爬行 - 可能是因為它試圖再次測量元素?

 public class TestPanel : Panel
{
    private int _rowHeight = 20;
    private int _columnWidth = 50;

    public TestPanel()
    {

        for (int i = 0; i < 100; i++)
        {

            for (int j = 0; j < 20; j++)
            {
                TextBlock cell = new TextBlock();
                cell.ClipToBounds = true;
                cell.Width = _columnWidth;
                cell.Height = _rowHeight;
                cell.Text = i.ToString() + ":" + j.ToString();
                this.Children.Add(cell);
            }
        }
    }

    protected override Size MeasureOverride(Size constraint)
    {
        return new Size(_columnWidth*20,_rowHeight*100);
    }

    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        UIElementCollection children = InternalChildren;

        for (int i = 0; i < 100; i++)
        {
            for (int j = 0; j < 20; j++)
            {
                UIElement child = children[i*20+j];
                child.Arrange(new Rect(j * _columnWidth, i * 20, _columnWidth, 20));
            }
        }
        return arrangeBounds;
    }
}

public MainWindow()
    {
        InitializeComponent();

        TestPanel myPanel = new TestPanel();
        ScrollViewer scroll = new ScrollViewer();

        myPanel.Background = Brushes.Aqua;

        scroll.Content = myPanel;
        this.Content = scroll;

    }

TextBox和Rectangle之間的性能差異是由於這些控件的復雜性不同。 只需比較結果可視化樹的復雜性(即使用XamlPad)。 矩形很可能只知道它所需的大小。 另一方面,TextBox在計算所需大小時需要考慮許多不同的因素,例如所需的實際文本大小(我猜這是真正的瓶頸)。

話雖如此,您可能需要嘗試一些優化。 度量通過的目標是確定您想要的大小。 此外,通過在所有子元素上調用measure來傳播度量傳遞。 但是,如果您希望更改所需大小,則只需執行此操作。 您似乎對包含_rowHeight和_columnWidth字段的布局了解很多。 所以做以下事情:

  • 使用以下child.Measure(new Size(_columnWidth, _rowHeight))測量您的孩子: child.Measure(new Size(_columnWidth, _rowHeight)) 這是實際的約束嗎?
  • 減少子元素的度量運行次數。 通過將所有這些代碼移出MeasureOverride並僅在_rowHeight或_lineWidth更改時調用此函數來執行此操作(此外,這將是在子元素上調用Measure的方法)。 將這些字段實現為DependencyProperties以便能夠監聽更改(如果您不喜歡DependencyProperties,可以使用INotifyPropertyChanged
  • 最有可能的是,您可以在常量時間內實現MeasureOverride(現在無需測量子元素)(例如numberOfColumns * _columnWidth...
  • 為ArrangeOverride實現類似的邏輯。
  • 換句話說:不要在MeasureOverride / ArrangeOverride中做布局邏輯(即決定諸如“這個元素是否適合這一行”這樣的問題)

但是,這種方法不符合TextBox元素的所需大小。 您可以不關心或單獨解決此問題:

  • 聽取文字變化,選擇合適的事件。
  • 如果TextBox中的文本發生更改,請僅為此特定文本框調用“測量”。 (您可以使用正無窮大作為約束來測量此文本框)
  • 調整ColumnWidth和RowHeight屬性

除了改進MeasureOverride / ArrangeOverride實現之外,您還可以為TextBox使用不同的(例如,更輕量級)ControlTemplate。 我會選擇重寫MeasureOverride / ArrangeOverride。

首先,在測試代碼后,您似乎已經重寫了WPF中已存在的WrapPanel 當我用WrapPanel替換TestPanel ,行為完全相同,性能也有所提高。

其次,我想知道什么樣的硬件,特別是你正在使用的視頻卡。 當我在我的電腦上運行這個樣本時,我看到很少甚至沒有滯后。 當然不是你所說的“停頓”。

最后,我所知道的提高文本呈現性能的唯一方法是使用低級文本對象。 想到FormattedText 然而,這比使用TextBlock要困難得多,因此我鼓勵您在切換到FormattedText之前考慮一下您要完成的任務。

編輯

WPF損害您性能的真實區域在布局系統的測量和排列過程中。 重要的是要理解每次調整窗口大小時,WPF都會重新計算每個用戶界面元素的大小和位置,然后相應地重新排列它們。 這對於實現靈活布局或創建動態用戶界面非常有用,但對於靜態數據網格(這似乎是您的想法),這樣做弊大於利。 在大多數機器上,WPF會盡可能多地卸載GPU。 但是,在您的情況下,CPU正在處理所有內容,因此您在調整大小時會看到“流失”。

FormattedText會更快,但不適合使用數據網格。 我不是編寫自己的布局面板(WPF中的1%場景),而是切換到ListView或第三方網格組件,看看性能是如何進行的。 構建(和優化)這些組件以顯示大量不斷變化的數據 - 構建WPF布局面板以包含其他用戶界面元素和繪圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM