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