2011-07-24 40 views
4

我一直在WPF DataGrid和listbox GridView性能顯示甚至少量的數據時遇到問題。我雖然這個問題只是WPF一般性能差,但問題似乎只在於文本塊控制。WPF文本塊性能差

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

它看起來像性能問題來自:

child.Measure(constraint); 

當文本塊被衡量的,它帶來的性能嘎然而止。有什麼我可以覆蓋文本塊的測量或某些東西來提高性能? (我會明確設置孩子的大小)

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

這段代碼的性能很好,除了......當textblock中文本的寬度超過文本塊的實際寬度時。這使我的表現回落到了可能的原因 - 可能是因爲它試圖再次測量元素?

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; 

    } 

回答

5

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

說了這麼多,你可能想嘗試一些優化。度量通過的目標是確定您所需的大小。此外,您通過調用所有子元素上的度量來傳播度量傳遞。但是,如果您希望更改所需大小,則只需執行此操作。看起來你知道很多有關_rowHeight和_columnWidth字段的佈局。所以做到以下幾點:

  • 測量你的孩子使用:child.Measure(new Size(_columnWidth, _rowHeight))。這是實際的限制嗎?
  • 減少您的子元素的度量運行次數。通過將所有代碼移出MeasureOverride並僅在_rowHeight或_lineWidth更改時調用此函數(同時,這將是您的子元素上調用Measure的方法)來完成此操作。實現這些字段爲DependencyProperties以便能夠監聽更改(如果您不喜歡DependencyProperties,則可以使用INotifyPropertyChanged
  • 最有可能的是,您可以在常量時間內實現MeasureOverride(現在不必測量您的子元素)(例如numberOfColumns * _columnWidth...
  • 爲ArrangeOverride實現類似的邏輯。
  • 換句話說:不做佈局邏輯(即決定象「此元件配合到這一行」的問題)在的MeasureOverride/ArrangeOverride

這種方法,然而,不尊重的所需尺寸TextBox元素。你可以不關心或分開解決:

  • 聽文本更改,選擇適當的事件。
  • 如果文本框中的文本發生更改,請僅爲此特定文本框調用「度量值」。 (你可以測量這個文本框與正無窮大的約束)
  • 適應您columnWidth中和rowHeight屬性

除了提高你的MeasureOverride/ArrangeOverride實現您可以使用不同的(例如更輕巧)的ControlTemplate對TextBox。我會選擇重寫MeasureOverride/ArrangeOverride。

+0

看來,即使我覆蓋佈局面板的度量替代,當文本長於塊時,也會出現一個度量。有沒有什麼好方法可以防止這種情況發生? – ChandlerPelhams

3

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

其次,我想知道什麼樣的硬件,特別是您使用的視頻卡。當我在PC上運行這個示例時,我幾乎沒有看到任何滯後。當然不是你正在談論的「打磨停頓」。

最後,我所知道的改進文本渲染性能的唯一方法是使用低級文本對象。想起了FormattedText。然而,這與TextBlock相比要困難得多,所以我鼓勵你在轉換到FormattedText之前考慮你想要完成的是什麼。

編輯

其中WPF是傷害你的表現真正的區域是在測量和安排layout系統的通行證。理解每次調整窗口大小都很重要,WPF正在重新計算每個用戶界面元素的大小和位置,然後相應地重新排列它們。這對於實現靈活的佈局或創建動態用戶界面非常有用,但是對於靜態數據網格(這似乎是您的想法),這樣做會帶來更多的負面影響。在大多數機器上,WPF將盡可能多的工作分配給GPU。然而,在你的情況下,CPU正在處理所有事情,因此你在調整大小時看到的「流失」。

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

+0

好吧,我目前在我的筆記本電腦上安裝了T4200(2.00 Ghz雙核),帶有2個內存和板載顯卡 - 這是我工作時計算機上的一個步驟,它可以運行這個 - 〜3GHz學校奔騰4 W /沒有專用顯卡。我知道我重新編寫了包裝面板 - 我的最終目標是創建一個數據網格,但我現在只想測試面板...您認爲FormattedText會比TextBlock快得多嗎? – ChandlerPelhams

+0

查看我上面的編輯。 – Charlie

+0

感謝您的額外輸入。我以前曾嘗試使用listview,與標準數據網格相比,性能提升最小,此時不可能使用第三方控件。我對編寫自定義面板還是比較陌生 - 是否有一種簡單的方法來編寫排列和度量過程,以便不必執行復雜的計算,如果我知道每個cild的大小,確切地說每行有多少個子節點,會有? – ChandlerPelhams