2013-01-24 50 views
2

我有一個綁定到BindingSource的WinForms DataGridView,BindingSource又綁定到了100,000個對象的BindingList。爲WinForms DataGridView行設置背景色的最快方法

BindingList<MyObject> myObjectList = new BindingList<MyObject>(); 
BindingSource bindingSourceForMyObjects = new BindingSource(); 

bindingSourceForMyObjects.DataSource = myObjectList; 
dataGridViewMyObjects.DataSource = bindingSourceForMyObjects; 

我有一個事件處理程序掛接到包含下面的代碼我的DataGridView的CellValueChanged事件:

dataGridViewMyObjects.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Red; 
dataGridViewMyObjects.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.White; 

所以,當我的用戶更改一行時,此事件處理程序火災和行變爲白色紅色表示數據已更改。這很好,但我也有一些情況,我需要以編程方式更改基礎列表,我也希望這些更改反映在DataGridView中。爲了達到這個目的,我的對象類實現了INotifyPropertyChanged,並且我有一個事件處理程序連接到我的BindingSource的ListChanged事件。在該事件處理程序的代碼看起來是這樣的:

if (e.ListChangedType == ListChangedType.ItemChanged) 
{ 
    dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.BackColor = Color.Red; 
    dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.ForeColor = Color.White; 
} 

這也是工作,所以如果我編程修改對象50,在DataGridView行得到更新。但是,正如我之前所說的,我有100,000個對象正在處理中,如果我需要修改超過800個對象,則可能需要一段時間,因爲在對象中調用了OnPropertyChanged()。在絕對最壞的情況下,如果我需要修改所有100,000個對象,則發生這種情況可能需要將近1分鐘。

在我的對象類的內部,我有一個布爾變量,用於避免在編程性地執行「批量」更新(> 800個對象)時觸發OnPropertyChanged()調用。這使得非常快速地更新對象屬性,但是由於雙向綁定被繞過,DataGridView中的相應行不再更新它們的forecolor/Backcolor值。我知道哪些行對應於被修改的對象,並且我嘗試循環遍歷它們並更新ForeColor/BackColor值,但是再次完成此操作需要將近一分鐘。

我已經試過包裝在環...

dataGridViewMyObjects.SuspendLayout(); 
// loop here 
dataGridViewMyObjects.ResumeLayout(); 

,但似乎並沒有把性能差異。有沒有更快的方法來設置ForeColor/BackColor很多行,或者我看到的速度只是我正在使用的數據大小的問題?

+0

這不會是在WPF一個問題,有內置的UI虛擬化http://www.youtube.com/watch ?v = D3Y6DnFpHCA –

回答

2

有一點要嘗試的是告訴Windows停止繪製您的控件,而你循環你的變化。從How do I suspend painting for a control and its children?

class DrawingControl 
{ 
    [DllImport("user32.dll")] 
    public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam); 

    private const int WM_SETREDRAW = 11; 

    public static void SuspendDrawing(Control parent) 
    { 
     SendMessage(parent.Handle, WM_SETREDRAW, false, 0); 
    } 

    public static void ResumeDrawing(Control parent) 
    { 
     SendMessage(parent.Handle, WM_SETREDRAW, true, 0); 
     parent.Refresh(); 
    } 
} 

那麼你的代碼應該是這樣的:

DrawingControl.SuspendDrawing(dataGridViewMyObjects); 
// loop here 
DrawingControl.ResumeDrawing(dataGridViewMyObjects); 
+0

這使得在我的情況下着色速度稍快;還有其他的減速需要解決,但它們超出了這個具體例子的範圍。 – KeithS