Repeater?一個只會綁定數據並顯示數據的低級控件?哦~誰告訴你的?
Repeater因爲他的靈活性和擴展性很高,備受很多程序員青睞。我的一個.net羣成員曾因爲比較Repeater和GridView而爭得面紅耳赤。我個人也是因爲GridView有些功能無法實現,纔開始研究Repeater的。
當然了,我對GridView也不是太熟悉。無法客觀的比較兩者的優劣,但因爲GridView的高度封裝性註定了他的靈活性不及Repeater,而且Repeater做出來的東西比較“乾淨”(個人覺得)。
本着分享爲原則,特此將自己這段時間的研究成果在年前展現給大家。
這裏我將整合很多Repeater的應用,內容長是一定的(我會盡量以最簡單明瞭的形式展現,我知道讀者希望這樣。因爲我在學別人東西的時候也希望這樣。呵呵)。但每個內容板塊都是可以獨立的。OK,現在就開始了。
目 錄
1.Repeater的嵌套使用
2.Repeater裏的按鈕單擊事件
3.獲取子Repeater裏的控件
4.Repeater裏單選按鈕互斥問題
5.Repeater中記錄單選按鈕選擇狀態並顯示
1.Repeater的嵌套使用:
參考代碼:
前臺:
<asp:Repeater ID="questionTable" runat="server"
onitemdatabound="questionTable_ItemDataBound">
<itemtemplate>
<%#DataBinder.Eval (Container.DataItem ,"FID") %>
<asp:Repeater ID="questionOption" runat="server">
<itemtemplate>
<%#DataBinder.Eval (Container.DataItem ,"OPTIONNAME") %>
</itemtemplate>
</asp:Repeater>
</itemtemplate>
</asp:Repeater>
如果你仔細看了下結構,你是否會思考一個問題。如何對裏面嵌套的Repeater進行數據綁定呢?
接下來看後臺代碼。
後臺:
//用Repeater的ItemDataBound事件
protected void questionTable_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
System.Web.UI.WebControls.Repeater questionOption = (System.Web.UI.WebControls.Repeater)e.Item.FindControl("questionOption"); //獲取嵌套中的Repeater 這是關鍵
//接下來就可以把你的數據源給子Repeater了
questionOption.DataSource = "......" ; //給出要綁定的數據
questionOption.DataBind();
}
}
小結:
什麼時候用嵌套呢?當要綁定的數據存在主子表時,嵌套的Repeater就可以幫大忙了。外面的綁定主表數據,裏面的綁定子表數據。這樣顯示出來的情況是主表記錄顯示一行接着顯示一行子表記錄。以此類推。這是不是給人一種耳目一新的感覺呢?如果是多層嵌套也沒關係,就是不斷獲得子Repeater對象即可。
PS:要主表記錄行下面顯示對應主表的子表記錄,就看你給子Repeater綁定怎樣的數據源了。這裏就是看你如何傳值了,給怎樣的數據源了。
2.Repeater裏的按鈕單擊事件
參考代碼:
前臺:
<asp:Button ID="delete" runat="server" Text="刪除" OnCommand="deletequestionOption_Click"></asp:Button>
後臺:
protected void deletequestionOption_Click(object sender,CommandEventArgs e)
{
if ((sender as System.Web.UI.WebControls.Button).Text == "刪除")
{
//如何獲取控件對象呢,彩色的代碼就是獲取的方法
}
}
小結:
你想過用Repeater來編輯顯示出來的數據嗎?比如刪除或修改數據。在Repeater裏面放入Button。通過OnCommand屬性來產生一個事件,以便達到編輯數據的效果。
3.獲取子Repeater裏的控件
參考代碼:
前臺:
<asp:Repeater ID="questionTable" runat="server"
onitemdatabound="questionTable_ItemDataBound">
<itemtemplate>
<asp:Repeater ID="questionOption" runat="server">
<itemtemplate>
<asp:TextBox ID="option" runat="server" Text='<%#DataBinder.Eval (Container.DataItem ,"OPTIONNAME") %>'></asp:TextBox>
</itemtemplate>
</asp:Repeater>
</itemtemplate>
</asp:Repeater>
後臺:
//ItemCommand事件是Repeater中生成事件時激發(也就是Repeater裏面的事件都會觸發此事件)
protected void questionTable_ItemCommand(object source, RepeaterCommandEventArgs e)
{
System.Web.UI.WebControls.TextBox Toption = null;
string toption = null;
System.Web.UI.WebControls.Repeater rptchild = (System.Web.UI.WebControls.Repeater)e.Item.FindControl("questionOption");
//先獲取子Repeater
for (int j = 0; j < rptchild.Items.Count; j++) //通過循環遍歷來獲取
{
//找到子級Repeater中的控件
Toption = (System.Web.UI.WebControls.TextBox)rptchild.Items[j].FindControl("Toption");
toption = Toption.Text;
}
}
4.Repeater裏單選按鈕互斥問題
有時需要往Repeater中加入單選按鈕,當我們加入<asp:radioButton/>這個控件後,發現無論自己如何設置GroupName屬性也無法使其互斥(每個單選都能被選中)。爲什麼會這樣呢?
這是因爲放入Repeater中的單選按鈕控件自動生成的RadioButton的GroupName不是唯一的,是依據“模板行ID+radiobutton的ID”(如:Repeater1_ctl02_CustomerRadio1,Repeater1_ctl03_CustomerRadio1)
瞭解原因後,所以解決方法有兩種,一種是重寫<asp:radioButton/>控件(重寫,估計你會崩潰的)。令一種就是用<input type="radio"/>來解決。
我選擇最簡單的第二種,真的很簡單。網上有一種方法也用到了<input type="radio"/>但是都用到了大量的JavaScript。很頭疼的說,都挺複雜的。
我們知道<input type="radio"/>分組的屬性是name。所以當你設置name屬性後,就會發現所有行的單選按鈕都互斥(因爲所有的name都相同),正好與<asp:radioButton/>走了另一個方向的極端。所以必須綜合思考下。
我們可以通過獲取Repeater顯示行的行號來表示name,那樣就可以讓每行的單選按鈕互斥了。所以獲取行號的方法如下:
<input type="radio" id="Radio" name="<%#Container..ItemIndex%>"/>
Container.ItemIndex是獲取Repeater的行號
如果你運用了嵌套Repeater,而且你的單選按鈕在子Repeater。那麼你的radio必須獲取父Repeater行號才行。方法如下:
<input type="radio" id="Radio" name="<%#((RepeaterItem)Container.Parent.Parent).ItemIndex%>"/>
5.Repeater中記錄單選按鈕選擇狀態並顯示
爲什麼要記錄,當你的Repeater具有分頁功能的時候。你每次點擊其它的頁面時,會將原來已被選中的radio全部還原成爲選中狀態。所以記錄下每頁的radio選擇情況就很有必要了。這裏用JavaScript來解決。
代碼如下:
function AddRemoveValues(oChk) {
var HdnSelectedValues = document.getElementById("ctl00_cphPostback_HdnSelectedValues"); //這裏隱藏控件的id是通過查看源碼獲得的 原因可能是因爲每個母版也裏面包含了其它自帶的隱藏控件
var names = document.getElementsByName(oChk.name); //這裏是獲取一行中的所有單選按鈕 爲下面來分別判斷那個是被選中的
for (var i = 0; i < names.length; i++)
if (names[i].checked) {
if (HdnSelectedValues.value.indexOf(oChk.value) < 0) { //如果隱藏控件裏面有這個值了,就不進行添加(防止用戶多次點擊已選中的單選按鈕)
HdnSelectedValues.value += "," + oChk.value;
}
}
else {
HdnSelectedValues.value = HdnSelectedValues.value.replace("," + names[i].value, ""); //沒有被選擇,則替換掉原來進去的值
}
}
<input type="radio" id="option" οnclick="AddRemoveValues(this)" value='<%# Eval("FID") %>' name="<%#((RepeaterItem)Container.Parent.Parent).ItemIndex%>"/>
<asp:HiddenField ID="HdnSelectedValues" runat="server" />
延伸:
雖然每次點擊的radio都被記錄了下來。那怎麼樣利用這些記錄的值來顯示出來呢?下面我們就談論這個問題。
同樣通過激發某個事件來激發一個腳本。腳本代碼如下:
function SelectStatus() {
var HdnSelectedValues = document.getElementById("<%=HdnSelectedValues.ClientID%>");
var radios = document.getElementsByTagName("input");
//獲取當前頁面所有的radio
for (var i = 0; i < radios.length; i++) {
if (radios[i].type == "radio") {
if (HdnSelectedValues.value.indexOf(radios[i].value) >= 0) { //如果該單選按鈕的值在隱藏控件裏則單選爲被選狀態
radios[i].checked = true;
}
}
}
}
PS: 值得注意的是,通過“HdnSelectedValues.ClientID”來獲取客戶端ID。比如我這裏查看到源代碼中的客戶端是ID的"ctl00_cphPostback_HdnSelectedValues",這就是爲什麼直接獲取“HdnSelectedValues”是沒用的