Repeater 無 HeaderTemplate/FooterTemplate 之外的包裝元素,其 Controls 集合直接包含 RepeaterItem 實例(類型為 RepeaterItemType.Item、AlternatingItem 等)。理解這點,三種遍歷寫法的本質差異一目瞭然。
foreach (Control c in this.Repeater1.Controls) {
var chk = c.FindControl("cbDelete1") as HtmlInputCheckBox;
if (chk != null) chk.Checked = true;
}
缺陷:
Controls 可能包含非 RepeaterItem 的字面內容控制項(LiteralControl 等),需額外型別檢查。Repeater.Controls 非公開設計意圖,未來版本可能變更。for (int i = 0; i < this.Repeater1.Items.Count; i++) {
var chk = this.Repeater1.Items[i].FindControl("cbDelete1") as HtmlInputCheckBox;
if (chk != null) chk.Checked = true;
}
優點:
Items 集合僅包含 RepeaterItem,型別純淨。ItemIndex(即 i),便於對應資料源索引。RepeaterItemType 判斷:Items[i].ItemType == ListItemType.AlternatingItem。foreach (RepeaterItem item in this.Repeater1.Items) {
var chk = item.FindControl("cbDelete1") as HtmlInputCheckBox;
if (chk != null) chk.Checked = true;
}
優點:
item.ItemIndex、item.ItemType、item.DataItem。for 迴圈,效能無差異。// 假設資料源為 List
foreach (RepeaterItem item in Repeater1.Items) {
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem) {
Product product = (Product)item.DataItem; // 強型別轉換
var chk = item.FindControl("cbDelete1") as HtmlInputCheckBox;
if (chk != null) {
chk.Checked = product.IsDeletable;
chk.Attributes["data-id"] = product.Id.ToString();
}
}
}
| 維度 | Controls 遍歷 | Items 索引 | Items foreach |
|---|---|---|---|
| 型別安全 | 低 | 高 | 高 |
| 可讀性 | 低 | 中 | 高 |
| 索引需求 | 需手動計算 | 原生支援 | item.ItemIndex |
| 資料項存取 | 困難 | Items[i].DataItem | item.DataItem |
| 推薦度 | ❌ | ✅ (需索引運算時) | ✅✅ (首選) |
ItemType 為 Header/Footer,DataItem 為 null,務必判斷 ItemType 後再轉型。runat="server"。DataBind() 之後、PreRender 之前執行,否則 Items 為空。