天天看點

網格中合并(Merge)功能的多種技術方案

寫這篇文章,主要是因為我們的“下午茶時間”(項目内部的一種交流方式)激烈地讨論了此類功能的多種實作,我感覺非常有意思。大家可以參考一下。

我先簡單地描述一下功能要求,要求設計一種資料結構,支援網格控件(圖形化)實作矩形區域的合并效果(Merged)。非矩形區域的合并不在支援範圍之内。

大家可能都在使用各種各樣的網格控件,最出名的可能是FlexGrid。不過大家可以也思考思考,如果是你的話,你會如何設計呢?

有一個最基本的方法,每一個網格CELL中預置一個變量:MergeID。我們姑且将這種方法稱之為"MergeID法"。此方法規則比較簡單:沒有合并的CELL的MergeID都是0,相鄰矩形區域的合并CELLs的MergeID相同,且不為0。将0特殊處理,是為了加快處理速度,畢竟,大多數都是沒有合并的CELL。

1

如上面的網格,則左上角六個CELL合并,右下角四個CELL合并。

這種方法的最大問題在于,空間占有比較浪費,特别是對那些從沒有合并的CELL。另外,對于合并格的描述不清晰,整個網格中有多少合并格也不能簡單擷取,必須經過周遊才知道。

針對上面的分析,提出第二種方案,我們稱之為"MergeRange List",這種方法的最大優勢在于将所有合并的矩形區域統一管理起來,形成一個清單。網格控件在通路Merge屬性的時候,再到Range清單中查找,如果找到,則屬于合并格,否則為非合并格。

這個方式在FlexGrid就被使用。顯然這種方法比較成熟。不過這種方式在管理對象的時候,不容易對應。需要經過映射。這在需要大量通路網格CELL對象的時候,會産生一些效率浪費。

熟悉HTML的人,大概還知道HTML的表示方式,在網格上通過rowspan和colspan來定義。在有合并的CELL的左上角上,定義其向右和向下的合并範圍。通過這個範圍定義,我們也可以确定合并區域。這種方式的定義簡單。不過實作起來,其實有一些問題。

我們上面讨論幾種方案的時候,忽略了一個問題,那就是我們一般的網格結構,很可能是一個CELL對應一個對象。那樣的話,我們可以有一個新的方案,這個方案和第一個MergeID方案聯系在一起,但是我們不需要額外的MergeID屬性,而是直接使用Object的對象指針。隻需要判斷CELL周圍的對象是否相等,就可以知道其合并範圍。合并區域的所有CELL的對象相同。這樣,在取資料的時候,不需要進行額外映射。而在網格控件繪制的時候,才需要合并區域查找。效率應該可以滿足。我們就将這種方法叫"Ojbect/MergeID"吧。

  1. MergeID
  2. MergeRange List
  3. Span
  4. Object/MergeID

繼續閱讀