2008-10-07 48 views
10

我很希望有一箇中繼器生成一堆複選框,例如:ASP.NET:如何訪問中繼器生成的表單輸入元素?

<tr><td><input type="checkbox" name="t" value="11cbf4deb87" /> <input type="checkbox" name="a" value="33cbf4deb87" />stackoverflow.com</td></tr> 
<tr><td><input type="checkbox" name="t" value="11cbf4deb88" /> <input type="checkbox" name="a" value="33cbf4deb87" />microsoft.com</td></tr> 
<tr><td><input type="checkbox" name="t" value="11cd3f33a89" /> <input type="checkbox" name="a" value="33cbf4deb87" />gmail.com</td></tr> 
<tr><td><input type="checkbox" name="t" value="1138fecd337" /> <input type="checkbox" name="a" value="33cbf4deb87" />youporn.com</td></tr> 
<tr><td><input type="checkbox" name="t" value="11009efdacc" /> <input type="checkbox" name="a" value="33bf4deb87" />fantasti.cc</td></tr> 

問題1:我要如何單獨當中繼器正在運行,所以我可以設置的獨特價值引用每個複選框?

做我的數據綁定它的東西,如:

<itemtemplate> 
    <tr> 
     <td> 
     <input type="checkbox" name="t" 
      value="<%# ((Item)Container.DataItem).TangoUniquifier %>" /> 
     <input type="checkbox" name="a" 
      value="<%# ((Item)Container.DataItem).AlphaUniquifier %>" /> 
     <%# ((Item)Container.DataItem).SiteName %> 
     </td> 
    </tr> 
</itemtemplate> 

還是我應該在OnItemDataBound莫名其妙定置了嗎?

<asp:repeater id="ItemsRepeater" 
     OnItemDataBound="ItemsRepeater_OnItemDataBound" runat="server"> 
    ... 
    <itemtemplate> 
     <tr> 
     <td> 
      <input id="chkTango" type="checkbox" name="t" runat="server" /> 
      <input id="chkAlpha" type="checkbox" name="a" runat="server" /> 
      <%# ((Item)Container.DataItem).SiteName %> 
     </td> 
     </tr> 
    </itemtemplate> 
    ... 
</asp:repeater> 


protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e) 
{ 
    // if the data bound item is an item or alternating item (not the header etc) 
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 
    { 
     // get the associated item 
     Item item = (Item)e.Item.DataItem; 

     //??? 
     this.chkTango.Value = item.TangoUniquifier; 
     this.chkAlpha.Value = item.AlphaUniquifier; 
    } 
} 

但是,如果我應該在代碼隱藏中引用它,我如何在代碼隱藏中引用它?我是否應該使用<INPUT>控件的(服務器端)id屬性來引用它?我意識到服務器端的控件ID與客戶端上的ID不同。

或者我必須做一些事情,我必須找到一個名稱爲「t」,另一個名稱爲「a」的INPUT控件? CheckBox允許我設置它的輸入值是什麼樣的控件?

protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e) 
{ 
    // if the data bound item is an item or alternating item (not the header etc) 
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 
    { 
     // get the associated item 
     Item item = (Item)e.Item.DataItem; 

     CheckBox chkTango = (CheckBox)e.Item.FindControl("chkTango"); 
     chkTango.Value = item.TangoUniquifier; 

     CheckBox chkAlpha = (CheckBox)e.Item.FindControl("chkAlpha"); 
     chkAlpha.Value = item.AlphaUniquifier; 
    } 
} 

問題2: 當用戶以後點擊提交,如何找到所有選中的複選框,或者更具體地說他們的價值觀?

我必須FindControl嗎?

protected void DoStuffWithLinks_Click(object sender, EventArgs e) 
{ 
    // loop through the repeater items 
    foreach (RepeaterItem repeaterItem in actionItemRepeater.Items) 
    { 
     Item item = repeaterItem.DataItem as Item; 

     // grab the checkboxes 
     CheckBox chkAlpha = (CheckBox)repeaterItem.FindControl("chkAlpha"); 
     CheckBox chkTango = (CheckBox)repeaterItem.FindControl("chkTango"); 

     if (chkAlpha.Checked) 
     {   
     item.DoAlphaStuff(chkAlpha.Name); 
     } 

     if (chkTango.Checked) 
     { 
     item.DoTangoStuff(chkTango.Name); 
     } 
    } 
} 

中繼器項目DataItem仍然存在於點擊事件處理程序中嗎?

回答

13

當你設置你的ItemDataBound值:使用服務器控件,而不是進行輸入控制RUNAT =服務器

<asp:CheckBox id="whatever" runat="Server" /> 

的,您使用的FindControl

CheckBox checkBox = (CheckBox)e.Item.FindControl("whatever"); 
checkBox.Checked = true; 

當你的項目,你也可以使用foreach構造中的項目使用FindControl。另外,根據數據綁定的方式,DataItem可能在回發後不再存在。

foreach (RepeaterItem item in myRepeater.Items) 
{ 
    if (item.ItemType == ListItemType.Item 
     || item.ItemType == ListItemType.AlternatingItem) 
    { 
     CheckBox checkBox = (CheckBox)item.FindControl("whatever"); 
     if (checkBox.Checked) 
     { /* do something */ } 
    } 
} 
  • 很多人都在使用as運營商FindControl()誘惑 '安全投'。我不喜歡那樣,因爲當你改變窗體上的控件名稱時,你可以默默地忽略一個開發錯誤並且使其更難追蹤。我試圖只使用as運營商,如果控制不能保證在那裏。

更新:哪個CheckBox是哪個?在渲染HTML你最終會具有類似於

ctl00_cph0_ParentContainer_MyRepeater_ctl01_MyCheckbox 
ctl00_cph0_ParentContainer_MyRepeater_ctl02_MyCheckbox 
ctl00_cph0_ParentContainer_MyRepeater_ctl03_MyCheckbox 

你不在乎的名稱是什麼,因爲在foreach item.FindControl()獲取他們爲你,所有這些複選框的名字,你不應該假設他們。但是,當您通過foreach進行迭代時,通常需要一種方法將其引用回來。大多數情況下,這是通過在每個CheckBox旁邊放置一個asp:HiddenField控件來完成的,該控件包含一個標識符以將其匹配回正確的實體。

安全說明:使用隱藏字段存在安全問題,因爲可以在javascript中更改隱藏字段;請始終注意,在提交表單之前,此值可能已由用戶修改。

4

您可能會發現使用CheckBoxList控件更容易。

在簡單情況下,您可以將DataTextVield和DataValueField設置爲從數據源(假設您從數據源填充)拉出的名稱和值,然後綁定它以創建項目。

您的工作可能比在中繼器中創建複選框要少。

+1

我特意增加了兩個複選框,迫使回答這個概念的問題;否則人們會試圖找到捷徑。 – 2008-10-07 19:36:15

+0

我目前需要添加一些額外的細節到我的複選框列表 - 第三個數據元素 - 因此不能使用CheckBoxList控件,而是使用Repeater。 – 2009-12-02 16:23:44

2

這裏是如何處理的隱藏領域的一些具體代碼:

MARKUP:

<asp:HiddenField ID="repeaterhidden" Value='<%# DataBinder.Eval(Container.DataItem, "value")%>' runat="server" > 

C#:

{

HiddenField hiddenField = (HiddenField)item.FindControl(repeaterStringhidden); 

{ /* do something with hiddenField.Value */ 

}

1

我相信這一點KB給了我最好的答案:

http://msdn.microsoft.com/en-us/library/1d04y8ss.aspx

我自己缺乏運氣,這似乎是隻適用於.NET 4.0版本(和我仍然停留在3.5 SP1)。

引用(粗體是礦):

當控制是生成控制的重複實例數據綁定控件內,ASP.NET對的每個實例生成的UniqueID和客戶端ID的值控制。 UniqueID值是通過組合命名容器的UniqueID值,控件的ID值和序號生成的。在DataList,Repeater,GridView和ListView控件等控件中就是這種情況。

ASP.NET在ClientIDMode屬性設置爲AutoID時以類似的方式生成ClientID值。這可能會導致難以在客戶端腳本中引用該控件,因爲您通常無法預測所使用的連續數字的值。如果你想從客戶端腳本訪問數據綁定控件,你可以設置ClientIDMode屬性爲可預測。這使得更容易預測ClientID值將會是什麼。

當您設置的ClientIDMode可預測的,你可以也ClientIDRowSuffixDataKeys屬性設置成唯一,數據字段的名稱,如在數據庫表的主鍵。這會導致ASP.NET生成客戶端ID,如果您可以預測數據鍵值,則客戶端ID將更容易預測並引用客戶端腳本。

因此,在版本3。5,我使用隱藏域這樣做:

foreach (RepeaterItem item in rptClientes.Items) 
    { 
     Panel pnl = (Panel)item.FindControl("divCliente"); 
     Control c = pnl.FindControl("hdnID"); 
     if (c is HiddenField) 
     { 
      if (((HiddenField)c).Value == hdnClienteNome.Value) 
       pnl.BackColor = System.Drawing.Color.Beige; 
     } 
    }