轉帖|其它|編輯:郝浩|2011-08-22 15:08:21.000|閱讀 507 次
概述:一種改善控件性能的方法是,當需要對許多單元格進行變動時,可以先保持或掛起重畫,直到所有的變動都完成時再進行。通過在對單元格修改和重算時保持重畫(掛起布局),然后再恢復布局并重畫所有單元格控件能夠節省很多時間,并且仍然能為用戶展現一個全新的界面。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
一種改善控件性能的方法是,當需要對許多單元格進行變動時,可以先保持或掛起重畫,直到所有的變動都完成時再進行。通過在對單元格修改和重算時保持重畫(掛起布局),然后再恢復布局并重畫所有單元格控件能夠節省很多時間,并且仍然能為用戶展現一個全新的界面。
布局對象
布局是一個對象,它保存了計算后的值(像單元格的寬度和高度,合并,以及視圖),用來繪制控件的當前狀態。這些值可能包括到底有多少視圖,每一個視 圖左上方的單元格是什么,每一行及每一列有多大以及每一個視圖有多少單元格是當前可見的,等等。使用布局對象的目的是,通過保存繪制控件過程所使用已計算 好的布局值,每次控件重畫時重新使用它們而不是每次都進行重算,來優化控件的繪制。當跟蹤到一個需要重新生成布局對象的改變發生時,繪制代碼就會丟棄現有 的布局對象,并計算出一個新的對象。布局對象不屬于公共API,但是它們緩存了繪制表單所需的所有信息,像列寬,行高,單元格合并,單元格溢出以及總是可 見的長方形單元格標注(Cell.NoteStyle = NoteStyle.StickyNote)。
暫停布局邏輯
為了改善性能,你可以暫停布局,這樣可以暫停布局對象的更新,因此控件不會在重畫的計算上花費時間,直到恢復布局。兩個方法可以完成這些操 作,FpSpread類中的SuspendLayout 和ResumeLayout方法。一定要在一個特定操作的范圍內同時使用這兩個方法,否則暫停布局后就會出現問題,不能恢復。
當對表單進行修改時,SuspendLayout 方法能夠阻止控件重新計算列、行和單元格的布局。如果你在一個代碼塊中對表單做了大量的變動,使用SuspendLayout方法可以避免控件在每一次變 動發生時對布局對象所做的多余的中間計算,在所有變動完成之后使用ResumeLayout(true)方法重新計算布局對象。這樣可以極大的提高控件的 性能;另外基于表單所需要的特性,還有許多其他方法可以提高控件的性能。
System.DateTime st = System.DateTime.Now;
FpSpread1.SuspendLayout();
FpSpread1.Sheets(0).ActiveSkin = FarPoint.Win.Spread.SheetSkin.Load("d:\\temp\\skin.skn");
FpSpread1.ResumeLayout();
MsgBox("Duration (ticks)=" & System.DateTime.Now.Ticks - st.Ticks)
private void PerformInitialSetup()
{
// (0) used for property labels.
_propertyLabelOrdinal = 0;
// Set up the spread
spread.SuspendLayout();
SheetView sheet = spread.ActiveSheet;
sheet.Models.ColumnHeaderData =
new HeaderDataModel(spread, _orientation);
sheet.Models.Style = new SheetStyleModel(_orientation);
spread.NamedStyles = _config.Styles.NamedStyles;
// Insert initial data
sheet.Columns.Count = 2;
foreach (Block block in _config.Blocks)
{
// Insert any leading blank rows
if (block.SpaceBefore > 0) sheet.Rows.Add(sheet.Rows.Count, block.SpaceBefore);
if (block.DealProperties != null)
{
int rowIndex = sheet.Rows.Count;
sheet.Rows.Add(rowIndex, block.DealProperties.Count);
foreach (DealProperty property in block.DealProperties) {
sheet.Cells[rowIndex, _propertyLabelOrdinal].Value = property;
sheet.Rows[rowIndex].StyleName = block.StyleName;
rowIndex++;
}
}
// Insert any trailing blank rows
if (block.SpaceAfter > 0) sheet.Rows.Add(sheet.Rows.Count, block.SpaceAfter);
}
// Set initial styles
sheet.Columns[_propertyLabelOrdinal].StyleName = "dealPropertyLabels";
spread.ResumeLayout();
}
暫停通知
當布局被暫停后,如果沒有在同一個代碼塊中有相應的恢復方法就會出現異常,控件會顯示一個通知“布局處于暫停狀態”。如果控件的狀態變成這樣,說明 布局對象包含了非法的數據(大多數情況下為錯誤的數值),當控件使用非法的布局數據繪制時就會導致異常發生。在繪制控件過程中,如果發生未被捕捉的異常, 通知就會出現,并且在異常發生時布局也會被暫停。
這些只會在使用SuspendLayout方法暫停布局時才會發生,然后對控件狀態所做的改變也會生效,控件也會以某種方式使用非法的布局對象進行 再次繪制。也可能存在這樣的異常,它導致上述消息的顯示,但卻與暫停布局無關;例如,IRenderer.PaintCell方法調用過程中由自定義單元 格類型對象拋出的異常。對控件狀態所做的任何修改都會觸發布局的重計算,但并非所有的改動都是這樣。對行或列進行重新排列時,如排序和過濾,肯定需要重計 算,但設置文本只有在某些情況下才需要重計算,例如,當你將AllowCellOverflow屬性打開時。即使布局被暫停,Spread控件仍然可以使 用之前的正確布局信息來繪制控件;但之后Spread控件可能會產生不可預知的情況,例如,當你想要滾動頁面而控件卻沒有反應,也沒有顯示異常通知。
其他改善性能的方法
如果你不使用手寫便箋,那么可以將AutoUpdateNotes屬性設置為false,阻止控件對必須被設置為可見或隱藏或可移動的手寫便箋進行 檢查。如果你使用了AllowCellOverflow屬性,將其關閉可以提高布局計算的性能,因為每次對單元格中的數據進行修改時,這個特性需要許多對 文本寬度的計算。如果你使用了公式,在更新之前將AutoCalculation屬性設置為false,然后再將其設回true,并調用 Recalculate方法,這樣可減少對公式的多余中間計算。
你還可以做一些其他的操作提高性能,如減小控件的大小,或減少一次性顯示的列數和行數(布局對象只計算表單的可見部分),或實現你自己的表單模型對 象(就像實現了ISheetDataModel接口的數據模型對象),刪除不需要的功能特性(例如,當你不需要數據綁定時,就不用實現數據綁定相關的接 口)。
同時使用兩個方法
大概的程序結構如下:
SuspendLayout
在這里插入你的代碼
ResumeLayout
這兩個方法用來暫時忽略對布局所做的修改,這樣可以進行許多修改操作,而不用在每次修改時進行多余的布局重計算。當布局計算被暫停時,跟蹤控件修改 的事件處理器不能對布局進行重計算,并且繪制代碼不會訪問新的布局。在使用嵌套循環修改每一個單元格時,像修改每一個單元格的值,這種情況肯定可以從先暫 停布局,然后再恢復布局的方式中獲益。
請記住,如果在對控件進行修改時不能從暫時停止布局中獲得性能提升,就不要使用這些方法。一定要在同一個代碼塊中同時使用這兩個方法; 否則,如果調用 SuspendLayout方法時沒有在同一個代碼塊中相應的調用 ResumeLayout方法,控件可能無法正確的繪制。
在下面的示例代碼中,我們在修改單元格的代碼附近的代碼塊中同時使用了這兩個方法。在修改單元格的顏色時,代碼暫停了Spread控件的重畫,并在之后恢復了重畫。
fpSpread1.SuspendLayout();
fpSpread1.Sheets[0].Cells[0, 0, 499, 499].BackColor = Color.White;
fpSpread1.ResumeLayout(true);
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客園