我們在綁定到對象集合的窗口上有數據網格。我們在這個窗口上表現非常糟糕;加載需要長達20秒,然後每次滾動數據網格時需要5-7秒。迄今共有12個項目。當我們調查時,看起來放緩的主要原因是財產吸收者;我們的一些獲得者被稱爲20,000次以上(每個對象1666.667次)!儀器顯示我們的吸氣劑不是特別是慢;最慢的一次花費了0.002秒。不幸的是,當你乘以0.0002 * 20k時,你很容易想到我們正在經歷的延遲。DataGrid過度數據綁定屬性獲取調用
我們坐下來創建了一個問題證明樣例項目。在這個項目中,我們創建了一個簡單的類,一個簡單的視圖模型和一個非常基本的窗口。我們添加了一些代碼來試圖觀察問題。雖然我們沒有看到任何接近之前我們看到的問題的嚴重程度,但這是一個更簡單的屏幕;對我們更令人不安的是,我們確實看到了我們認爲會「過度」使用財產獲得者的證據。在這個例子中,當你運行屏幕時,它們從1開始;當你向下滾動然後返回時,其中一些現在可以達到5或6;向下滾動,你會看到一些最底部的9個左右。
在這個概念證明的情況下,這不是問題;但我們的實際對象要複雜得多,而且我們無法承受40秒的延遲訪問房產20,000次!有人知道這裏發生了什麼嗎?我怎樣才能讓網格更積極地輪詢我的對象?我們正在使用WPF-Toolkit DataGrid和.NET 3.5版本。針對PoC樣本代碼如下:
***** WINDOW CODE *****
<Window x:Class="PocApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
Title="Window1" Height="200" Width="200">
<Grid>
<WpfToolkit:DataGrid ItemsSource="{Binding Path=MyEntries}">
</WpfToolkit:DataGrid>
</Grid>
</Window>
*****窗口代碼隱藏*****
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PocApp
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.DataContext = new EntryViewModel();
}
}
}
*****入門級*****
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PocApp
{
public class Entry
{
public Entry(string first, string last)
{
FirstName = first;
LastName = last;
}
public string FirstName
{
get
{
firstCall++;
System.Console.WriteLine("FirstName Call:" + firstCall);
return _firstname;
}
set
{
_firstname = value;
}
}
public int FirstNameCallCount
{
get
{
return firstCall;
}
}
public string LastName
{
get
{
lastCall++;
System.Console.WriteLine("LastName Call:" + lastCall);
return _lastname;
}
set
{
_lastname = value;
}
}
public int LastNameCallCount
{
get
{
return lastCall;
}
}
private string _firstname,_lastname;
private int firstCall,lastCall = 0;
}
}
*****輸入視圖模型類*****
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
namespace PocApp
{
public class EntryViewModel
{
public EntryViewModel()
{
List<Entry> myCoolEntries = new List<Entry>()
{
new Entry("A","A1"),
new Entry("B","B1"),
new Entry("C","C1"),
new Entry("D","D1"),
new Entry("E","E1"),
new Entry("F","F1"),
new Entry("G","G1"),
new Entry("H","H1"),
new Entry("I","I1"),
new Entry("J","J1"),
new Entry("K","K1"),
new Entry("L","L1"),
new Entry("M","M1"),
new Entry("N","N1"),
new Entry("O","O1"),
new Entry("P","P1"),
new Entry("Q","Q1"),
};
MyEntries = (CollectionView)CollectionViewSource.GetDefaultView(myCoolEntries);
}
public CollectionView MyEntries
{
get;
private set;
}
}
}
我們發現了這個問題。在我們的實際實現中,綁定的對象是DataRow對象的包裝器。他們依靠DataTable.RowChanged事件爲它們處理NotifyPropertyChanged。事實證明,當這些行滾動進入和離開視圖時,RowChanged事件被激發多次。禁用該事件使我們的通話總數從200k +增加到50左右。感謝關於NotifyPropertyChanged的提示。 – GWLlosa 2010-09-17 14:31:44