前言
合併儲存格這需求,相信很多作Web的人都有碰到過,也有許多文章用不同的方式實作。在ASP.NET Webform來說,基本上不外乎就是三種方式:
合併儲存格這需求,相信很多作Web的人都有碰到過,也有許多文章用不同的方式實作。在ASP.NET Webform來說,基本上不外乎就是三種方式:
- GridView在PreRender時針對每一列去檢查並做合併row的動作。
- 巢狀的GridView/ListView,來呈現一對多的物件集合關係。
- 使用jQuery在HTML Render完後,去做td的RowSpan。
通常合併儲存格要呈現的資料關係,就是一對多的關係,例如:主單與子單、客戶與訂單、角色與人員等等…這篇文章針對的,就是以Entity為觀念當出發點,當Entity是一對多的集合時,該怎麼樣使用ListView,並用jQuery來達到rowspan的效果。(jQuery的部份,則是使用黑暗執行緒的以jQuery實現Table相同欄位的上下合併)
需求
以Role-Person為例,一個角色可以有多個人的情況,最後要呈現出所有角色其對應的相關人員資料。Entity如下:
Person
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
}
{
public string Id { get; set; }
public string Name { get; set; }
}
實作
不是把資料餵給ListView,再套用黑大的jQuery就可以了嗎?很不幸的,不是這麼單純。
將上面的資料餵給ListView,得到的會是2筆Role的資料,也就是ListView只會呈現2筆record,那就無法作RowSpan。所以這邊的需求就是,需要將資料從List<Role>轉成List<Person>,且每一筆Person,還要帶著RoleId的資訊。就這麼簡單,這個部分搞定,其他的就都不難。
資料來源的改變
怎麼樣把資料從一對多,轉成多筆資料帶著『一』的相關資訊?用loop就遜掉了。江湖一點訣,只要懂LINQ的SelectMany,要達到這個目的就輕而易舉了。
Sample.aspx.cs
不是把資料餵給ListView,再套用黑大的jQuery就可以了嗎?很不幸的,不是這麼單純。
將上面的資料餵給ListView,得到的會是2筆Role的資料,也就是ListView只會呈現2筆record,那就無法作RowSpan。所以這邊的需求就是,需要將資料從List<Role>轉成List<Person>,且每一筆Person,還要帶著RoleId的資訊。就這麼簡單,這個部分搞定,其他的就都不難。
資料來源的改變
怎麼樣把資料從一對多,轉成多筆資料帶著『一』的相關資訊?用loop就遜掉了。江湖一點訣,只要懂LINQ的SelectMany,要達到這個目的就輕而易舉了。
Sample.aspx.cs
這邊用到的SelectMany是使用:
- 第一個參數是Func<TSource, IEnumerable<TCollection>>,TSource指的便是List<Role>,而return的TCollection,則是每一個Role裡面的People屬性,也就是List<Person>。這意味著最後的結果筆數要以List<Person>為主,而最後所有的List<Person>都會被攤平成IEnumerable<Person>。
看一下參數的命名是collectionSelector,也就是選出要當collection的集合。
- 第二個參數是Func<TSource, TCollection, TResult>,input有兩個參數,x就是TSource型別,也就是List<Role>。y就是TCollection型別,也就是第一個參數的結果,也就是Person的集合。return的則是TResult,也就是可以自己定義return的型別為何,會影響最後var result的型別。在這邊範例使用的匿名型別,也就是new{ RoleId=x.Id, Person=y }。代表一個匿名型別,有RoleId的屬性,並assign 原本List<Role>裡面,每一筆的RoleId。有一個Person的屬性,assign SelectMany第一個參數的結果中每一筆的Person。
看一下參數的命名是resultSelector,也就是選出最後的結果。而第一個參數與第二個參數的TCollection型別是一樣的,在第一個參數是collectionSelector這個委派的結果型別,第二個參數則是resultSelector這個委派的輸入參數型別,可以想像在背後的運作,應該是將第一個委派的集合,當做第二個委派的input參數。
- Result的結果:
jQuery的使用
.aspx的部份
js的部份
在aspx,在ListView上增加一些控制項,用來測試當ListView是可編輯或是非純文字的情況,功能一樣可以正常運作。最後也增加了一個Button,來確定即使合併儲存格後,仍可以得到ListView上server control的資料。
[註]這邊合併儲存格的條件是用$lastCell.text(),若要比較整個html,請改用html(),但html()在這個case裡面會碰到DOM的id不同,導致判斷這兩個cell不一致的情況。anyway,了解了原理,要怎麼變化就取決於各位的需求囉。
結果畫面
輸入資料,按按鈕後
結論
[註]這邊合併儲存格的條件是用$lastCell.text(),若要比較整個html,請改用html(),但html()在這個case裡面會碰到DOM的id不同,導致判斷這兩個cell不一致的情況。anyway,了解了原理,要怎麼變化就取決於各位的需求囉。
結果畫面
輸入資料,按按鈕後
結論
- 巢狀的物件集合,需要攤平的時候,可以透過SelectMany來做,不要害怕委派方法跟泛型,了解之後會更能體會設計的藝術與美。
- 黑大的文章,向來目標明確,舉例淺顯易懂,程式精簡,且看了不只考試可以得一百分,還能會心一笑,實在是居家旅行,必備良藥。
Sample Project:ListViewRowSpan.zip
沒有留言:
張貼留言