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