轉帖|其它|編輯:郝浩|2011-08-16 14:39:28.000|閱讀 457 次
概述:Spread控件提供了很多模型,這些模型提供了自定義控件的基礎架構。同時,這些模型作為底層模板,派生出了更多通用的快捷對象。在 不使用Spread的底層模型的情況下,你可以完成許多任務。通過使用Spread設計器或者快捷對象(如單元格、列和行)的屬性,你可以在表單上實現許 多改變。但是因為表單模型是所有快捷對象的基礎,因此在通常情況下,使用表單模型要比使用快捷對象的速度要快。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
Spread控件提供了很多模型,這些模型提供了自定義控件的基礎架構。同時,這些模型作為底層模板,派生出了更多通用的快捷對象。
在 不使用Spread的底層模型的情況下,你可以完成許多任務。通過使用Spread設計器或者快捷對象(如單元格、列和行)的屬性,你可以在表單上實現許 多改變。但是因為表單模型是所有快捷對象的基礎,因此在通常情況下,使用表單模型要比使用快捷對象的速度要快。例如,在代碼中使用快捷對象設置一個屬性 值:
fpSpread1.Sheets[0].Cells[0, 0].Value = "Test";
這與下面使用底層數據模型的方式等價:
fpSpread1.Sheets[0].Models.Data.SetValue
(fpSpread1.Sheets[0].GetModelRowFromViewRow(0), fpSpread1.Sheets[0].GetModelColumnFromViewColumn(0), "Test");
快 捷對象訪問的是底層模型。當你使用快捷對象時,你實際上在使用控件的模型。作為一名開發人員,如果你想完全理解Spread的工作方式,想使用那些為你提 供的豐富特性和自定義功能,你就需要理解底層模型的使用方法。例如,你可以用這種方法為你公司所有的開發者創建一個模板控件。基于這些模型中的一種創建你 自己的類,你可以自定義該類并提供給所有的開發者使用。
使用底層模型有以下好處:
表單模型是一個集合,包含了所有對象的基礎設置以及某個特定表單的設置項。如果在Spread控件中有多個表單,那么每一個表單都有一個它自己的模型集合。
控件中表單的某些部分是由底層模型管理的,下圖對模型做了概念性的描述。
想 要把使用模型描述清楚并不容易,因為涉及到許多接口。每一個模型類都實現了許多接口,并且每一個模型都要實現一個特定的“模型”接口,使其作為該特定模型 的合法實現。所有對模型類的引用都是通過接口實現的,并且不要猜想每一個模型中都實現了哪些接口(除了“模型”接口必須暴露出來之外)。如果模型類沒有實 現一個特定的接口,那么該功能就不能在表單中使用(例如,如果SheetView.Models.Data沒有實現IDataSourceSupport 接口,那么DataSource和DataMember屬性將不起作用)。如果想獲取這些接口的完整列表,你可以在線幫助文檔中查看相關信息 。
Spread控件提供了如下模型,這些模型提供了許多可以在控件上使用的自定義設置項。
表單模型 | 類和接口 |
描述 |
軸模型 | BaseSheetAxisModel
DefaultSheetAxisModel ISheetAxisModel |
該模型是表單中的單元格如何按行或列組織的基礎。 |
數據模型 | BaseSheetDataModel
DefaultSheetDataModel ISheetDataModel |
該模型是表單單元格數據操作的基礎。 |
選擇模型 | BaseSheetSelectionModel
DefaultSheetSelectionModel ISheetSelectionModel |
該模型是表單中被選中的單元格交互與行為的基礎。 |
合并模型 | BaseSheetSpanModel
DefaultSheetSpanModel ISheetSpanModel |
該模型是單元格如何進行合并的基礎。 |
樣式模型 | BaseSheetStyleModel
DefaultSheetStyleModel ISheetStyleModel |
該模型是表單單元格外觀樣式的基礎。 |
表單(SheetView對象)可以看作是五個底層模型(軸、數據、選擇、合并和樣式)的組合:
因 此,你對模型做的所有操作都會自動的在表單中進行更新,并且大部分的表單修改也會在模型中進行更新。對于單元格、行和列對象的設置也都是如此。對這些對象 的大部分修改都會自動更新到相應的表單模型設置中,反之亦然。如果你在數據模型中添加了一些列,它們也會被添加到表單中。甚至對于參數也同樣如此,例如, 只要表單未經過排序,數據模型GetValue和SetValue方法中的行和列參數,與表單中行和列的參數索引就是相同的。
并非所有 Spread名字空間的內容都包含在模型中。例如,控件的某些部分、表單標簽、表單背景色還有網格線,都沒有包含在模型中。但是對一個指定的單元格來說, 有意義的信息,如單元格的數據以及單元格的外觀,都被包含在模型中。表單的數據區域有自己的模型集;同樣的,行標題和列標題是另外兩個具有自己模型集的分 組,表角是另外一個具有自己模型集的分組。
每一個模型都包含一個基礎模型類,一 默認模型類和一個接口。默認模型是你在開發時最可能用到的模型;它提供了控件的默認特性,并且可以用來對模型進行小范圍的自定義設置。基礎模型是創建默認 模型的基礎,也可以通過它創建自定義模型。基礎模型包含最少的內置特性,默認模型對基礎模型進行了擴展。如果你想為你的應用程序提供不同的功能特性或者自 定義它的外觀和行為,你可以通過擴展基礎模型創建一個新類來實現。例如,你可以通過以上的方法為你公司的所有開發人員創建一個模板控件。基于基礎模型創建 自己的類,你可以創建自定義類,并把它提供給其他開發者使用。一般情況下,如果你在編輯模型,請使用默認模型類。但是如果你想(從頭開始)創建一個自定義 模型,請使用基礎模型類。
每一個默認模型類不僅實現了該模型類特有的接口,還實現了其他可選的接口。在模型類中,大多數功能(例如,公 式、數據綁定、XML序列化等等)都是可選的,并且是在與主模型接口(如ISheetDataModel)不同的接口中實現的。因此如果你想實現自己的模 型類,你可以自主選擇想要實現哪些功能。
模型與模型之間保持同步是很重要的,所以在組成表單的模型中,行數和列數是需要保持一致的。 SheetView對象通過SheetView.DocumentModels.Data屬性監聽ISheetDataModel.Change事件,并 且當行數或者列數通過以下方式改變時,會相應的對其他模型進行更新:
如果模型之間同步失敗,程序將拋出一個索引out-of-range異常,并嘗試獲取不存在的行或列的信息。
數據模型包含了單元格的內容,不管它是數值還是公式,或者是單元格的注釋或標記。數據模型在表單的數據域內包含了單元格的Value屬性,數據綁定表單的database屬性,以及其他與單元格內容相關的屬性。
數據模型是你在使用Spread控件時最有可能進行自定義設置的模型。相對于其他模型,數據模型實現了更多的接口,提供了更多可選擇的功能。例如,如果你想要實現類似于ActiveX Spread控件的未綁定虛擬模型功能,自定義數據模型就可以實現。
數據模型對象
數據模型是一個為單元格提供值的對象,這些值顯示在表單中。大多數情況下,創建時表單所創建的默認數據模型就能滿足你的需求。
默認數據模型DefaultSheetDataModel可 以創建用來存儲注釋、公式、標簽和值的對象。這些對象主要設計用來在內存使用和速度之間進行平衡,內存使用的大小和存取速度的快慢與數據模型的大小以及其 中數據的稀疏程度相關。如果你不使用注釋、公式以及標簽,這樣就不會占用很多內存,因為數據非常的稀疏。事實上這些對象并不會為數據申請內存,除非真的需 要。所以只要沒有在模型中設置注釋、公式或標簽,內存占用會一直很少。
默認數據模型可以在未綁定模式或綁定模式下使用。在未綁定模式 下,數據模型的表現像是一個儲存單元格值的二維數組。在綁定模式下,數據模型封裝了所提供的DataSource;如果需要,還可提供 DataSource中沒有的額外設置,例如,單元格公式,以及未綁定行或者列。
設置和添加數據模型
SetModelDataColumn方法與AddColumn方法的不同地方在于,你可以在數據模型中指定哪一個數據域綁定到哪一列上。
如 果你在模型中添加了一些列,那么這些列也會被添加到表單中。只要表單未經過排序,數據模型GetValue和SetValue方法中的行和列參數,與表單 中行和列的參數索引就是相同的。如果對表單的行或列進行了排序,那么視圖坐標必須通過SheetView.GetModelRowFromViewRow 和 SheetView.GetModelColumnFromViewColumn方法與模型坐標進行映射。
在數據模型 中,SheetView.GetValue方法和SheetView.SetValue方法經常用來獲取或設置數據。(這與調用 SheetView.Models.Data.GetValue和SheetView.Models.Data.SetValue等價。) 在SpreadView的SheetView中,當單元格處于編輯模式時,Cell.Value屬性返回editor控件中單元格的值。當單元格結束編輯 模式時,單元格的值就會在數據模型中進行更新。但是,你可以通過代碼手動把值更新到數據模型中:
SheetView.SetValue(row, column, SheetView.Cells[row, column].Value);
實現的接口
當 數據模型實現了IDataSourceSupport接口并被綁定到一個數據源時,數據模型中被綁定的部分就可以直接從數據源中獲取或設置數據。如果在數 據模型綁定數據源之后,使用AddColumns方法向其加入了一些列(對于這些列,IDataSourceSupport.IsColumnBound 返回false),那么這些列也可以是未綁定的。這些未綁定列的數據將會保存在數據模型中,而不是在數據源中。
如果數據模型也實現了 IUnboundRowSupport接口,那么數據模型中的行也可以是未綁定狀態的,并且這些行的數據也將保存在數據模型中而不是在數據源中。這些行可 以通過調用 IUnboundRowSupport.AddRowToDataSource函數轉換成綁定行,并且如果autoFill參數被設置為True,未綁定 的行中已綁定列的數據將以一條新的記錄或一個新的元素被添加到數據源中,假設數據源允許這樣的操作(如果它不允許這樣的操作時,你將會得到一個異常),這 樣一個未綁定的行就轉換成了綁定行。
默認的數據模型類,DefaultSheetDataModel,實現了所有的接口,以及許多與計算、層次和序列化相關的接口。
查看以下的代碼段,可以看到默認的數據模型和表單上的對象有什么不同。這段代碼把表單綁定到一個叫MyData的數據源上。
fpSpread1.Sheets[0].DataSource = MyData.Tables[0];
以及
FarPoint.Win.Spread.Model.DefaultSheetDataModel model = new FarPoint.Win.Spread.Model.DefaultSheetDataModel(MyData, strTable); fpSpread1.Sheets[0].Models.Data = model; |
在 第一個代碼段中,開發者使用現有的數據模型,并把它轉化為一個數據源; 在第二個代碼段中,開發者使用一個新的數據模型替換老的模型,并且丟棄老的數據模型。兩種實現方式的結果是相同的,但是第一種方式將導致老的模型變成垃 圾,并進行回收。通常你可能不想進行數據模型替換,除非你想創建屬于自己的數據模型類。一般情況下,沒有必要使用其他的 DefaultSheetDataModel替換數據模型,因為已經有一個在使用了。
速度和性能的平衡
如 果你從DefaultSheetDataModel 上派生,并使用GetValue和SetValue的實現來存儲數據,那么它將通過我們對稀疏數組和矩陣的實現在內存使用和訪問速度之間進行平衡。設計它 的目的是為了實現快速創建一個很大的模型(2億行*乘以2億列),并且能夠以合理的速度進行數據的獲取和設置,直到數據量變得很大(這種情況下,不管怎樣 你都將會耗盡內存)。當模型很大,并且很稀疏時(例如有至少三分之二是空的),訪問速度會變得很慢(需要使用二分查找法),并且內存使用效率也會降低。在 模型不是很大的情況下(少于32K行和列時),并且不稀疏(至少三分之一是滿的),訪問速度會很快(不需要使用二分查找法)并且內存使用效率很高。
你 可以先創建一個在窗體上使用Spread控件的測試工程,然后在該工程上運行一些簡單的測試,把表單的ColumnCount和RowCount屬性設置 為一個很大的值,你不會發現任何延遲;這是因為內存是基于實際數據項的大小來分配的。如果你開始在表單中填入大量數據,不久你就會感覺到延遲,尤其當可用 內存變小并且系統開始使用頁面文件來進行虛擬內存的交換的時候(僅在有大量數據時,才會發生這種現象)。
如果你需要獲取更多的細節,請參閱BaseSheetDataModel 類,DefaultSheetDataModel 類和ISheetDataModel 接口。
你可以以表單模型為模板來創建一個新的定制模型。例如,設想創建一個自定義數據模型。使用自定義數據模型,需要創建一個類并實現ISheetDataModel, 并在SheetView.Models.Data屬性中設置該類的實例。
假 設你不需要任何可選的接口,那么 ISheetDataModel 是唯一要求實現的接口。所有可選的接口都在DefaultSheetDataModel 中實現了。所以,當你想在自己的數據模型中實現它們時,可以很容易的僅僅實現 DefaultSheetDataModel的子類。
在BaseSheetDataModel 中,Changed事件也需要你來實現。
在產品實例Samples\CS\FreeCell文件夾中,有一個自定義數據模型的示例。這是FreeCell游戲在數據模型中的實現。
在 少數情況下,因為性能原因,你可能需要創建自己的自定義數據模型。例如,假設你想要顯示一個有一百萬行十列組成的大表,并且要計算它的值(如加法或者乘 法)。如果使用默認的表單數據模型,那么你需要計算和保存所有一千萬個值,這將會耗費大量的時間和內存。下面是一個代碼實例。
for (r = 0; r < 1000000; r++) for ( c = 0; c < 10; c++) spread.Sheets[0].Cells[r,c].Value = r + c; class ComputedDataModel : BaseSheetDataModel { public override int RowCount { get { return 1000000; } } public override int ColumnCount { get { return 10; } } public override object GetValue(int row, int column) { return row + column; } } |
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客園