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;
   }
}

Но если я должен ссылаться на него в коде, как я могу ссылаться на него в коде? Должен ли я ссылаться на него с использованием свойства id (server-side) элемента управления <INPUT>? я понимаю, что идентификатор элемента управления на стороне сервера не совпадает с идентификатором, который будет присутствовать на клиенте.

Или мне нужно что-то делать, когда я должен найти элемент управления INPUT с именем "t", а другой - с именем "a"? И какой контроль - это 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: Когда пользователь позже нажимает кнопку SUBMIT, как мне найти все отмеченные флажки, а точнее их значения VALUES?

У меня есть 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 еще в обработчике событий щелчка?

Ответ 1

Используйте серверный элемент управления вместо создания контроля ввода runat = server

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

Когда вы устанавливаете значение в ItemDataBound, вы используете FindControl

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

Когда вы получаете элементы, вы также используете FindControl из элемента в конструкции foreach. Кроме того, в зависимости от того, как вы его привязываете, 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, вам обычно нужен способ ссылаться на что-то. В большинстве случаев это делается с помощью asp: HiddenField управления рядом с каждой CheckBox для хранения идентификатора, чтобы он соответствовал правильному объекту.

Примечание по безопасности: существует проблема безопасности с использованием скрытых полей, потому что скрытое поле может быть изменено в javascript; всегда сознавайте, что это значение могло быть изменено пользователем перед отправкой формы.

Ответ 2

Вам может быть проще использовать элемент управления CheckBoxList.

В простом случае вы должны установить DataTextVield и DataValueField на имя и значение, как вытаскиваемые из вашего источника данных (при условии, что вы заселяетесь из источника данных), а затем привяжите его для создания элементов.

Вероятно, меньше работы с вашей стороны, чем создание флажков в ретрансляторе.

Ответ 3

Вот какой код для обработки скрытого поля:

MARKUP:

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

С#:

{

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

{ /* do something with hiddenField.Value */

}

Ответ 4

Я считаю, что этот КБ дал мне лучший ответ:

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

к моему собственному отсутствию удачи, похоже, это доступно только для версии .net 4.0 (и я все еще придерживаюсь 3.5 SP1).

цитирование (полужирный - мой):

Когда элемент управления находится внутри элемента управления с привязкой к данным, который генерирует повторяющиеся экземпляры элемента управления, ASP.NET генерирует значения UniqueID и ClientID для каждого экземпляра элемента управления. Значение UniqueID генерируется путем объединения значения уникального идентификатора контейнера Имени, значения идентификатора элемента управления и последовательного номера. Это происходит в таких элементах управления, как DataList, Repeater, GridView и элементы управления ListView.

ASP.NET генерирует значения ClientID аналогичным образом, когда для свойства ClientIDMode установлено значение AutoID. Это может затруднить ссылку на элемент управления в клиенте script, поскольку вы обычно не можете предсказать значения используемых последовательных чисел. Если вы хотите получить доступ к элементам управления с привязкой к данным с помощью клиента script, вы можете установить свойство ClientIDMode в Predictable.. Это упрощает прогнозирование значений ClientID.

Когда вы устанавливаете ClientIDMode в Predictable, вы можете также установить для свойства ClientIDRowSuffixDataKeys имя уникального поля данных, такого как первичный ключ в таблице базы данных. Это заставляет ASP.NET генерировать идентификатор клиента, который будет легче прогнозировать и ссылаться в клиенте script, если вы можете предсказать значения ключа данных.

Итак, в версии 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;
        }
    }