#c# #asp.net
Вопрос:
Я хотел найти идентификатор флажка и выбрать только один из нескольких флажков. Однако я не хочу использовать переключатели.
Вот что я сделал до сих пор, чтобы найти идентификатор флажков :
protected void gvChild_RowDataBound(object sender, GridViewRowEventArgs e)
{
foreach (GridViewRow row in gvParent.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
GridView gvChild = (GridView)row.FindControl("gvChild");
// Then do the same method for check box column
if (gvChild != null)
{
foreach (GridViewRow rowChild in gvChild.Rows)
{
if (rowChild.RowType == DataControlRowType.DataRow)
{
CheckBox chk = (CheckBox)rowChild.FindControl("CbList");
if (chk.Checked)
{
string strScript = "uncheckOthers(" ((CheckBox)e.Row.Cells[0].FindControl("CbList")).ClientID ");";
((CheckBox)e.Row.Cells[0].FindControl("CbList")).Attributes.Add("onclick", strScript);
testLabel.Text = strScript;
}
}
}
}
}
}
}
Я использую «uncheckOthers()» в качестве функции javascript, чтобы выбрать один и только один флажок.
ПРИМЕЧАНИЕ : Эта функция правильно работает в родительском представлении сетки.
Вот код этой функции :
function uncheckOthers(id) {
var elm = document.getElementsByTagName('input');
for (var i = 0; i < elm.length; i ) {
if (elm.item(i).id.substring(id.id.lastIndexOf('_')) == id.id.substring(id.id.lastIndexOf('_'))) {
if (elm.item(i).type == "checkbox" amp;amp; elm.item(i) != id)
elm.item(i).checked = false;
}
}
}
И последнее , но не менее важное: Разметка (удалены поля привязки в целях безопасности):
<asp:GridView ID="gvParent" runat="server" AutoGenerateColumns="false" CssClass="list" OnRowDataBound="OnRowDataBound" OnSelectedIndexChanged="gvParent_SelectedIndexChanged" DataKeyNames="MoodleTemplateID">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<img alt="" src="Images/view16x16.png"/>
<asp:Panel ID="pnlChild" runat="server" Style="display: none">
<asp:GridView ID="gvChild" runat="server" AutoGenerateColumns="false" CssClass = "list" DataKeyNames="ID" OnSelectedIndexChanged="gvChild_SelectedIndexChanged" OnRowDataBound="gvChild_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:CheckBox ID="CbList" runat="server"/>
</ItemTemplate>
<HeaderStyle Width="20px" />
</asp:TemplateField>
<asp:CommandField ButtonType="Image" SelectImageUrl="Images/edit16x16.png" ShowSelectButton="True" SelectText="Editar">
<ItemStyle Width="10px" />
</asp:CommandField>
</Columns>
</asp:GridView>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowSelectButton="True" SelectText="Editar">
<ItemStyle Width="10px" />
</asp:CommandField>
</Columns>
</asp:GridView>
Комментарии:
1. Эта логика не сработает. Скажем, 5 вариантов выбора для детей. Выбор 2 проверен. Если я сейчас проверю выбор 5, то вы запустите свой цикл, и когда вы обнаружите, что первый вариант проверен, вы отмените проверку всех. Так что теперь 2-й останется проверенным!!! Если вы хотите использовать обратный перенос для этого флажка, то вам даже не нужно зацикливать родительскую сетку, а можно просто получить идентификатор проверено, а затем отменить проверку всех остальных строк в этой дочерней сетке. Я опубликую решение, но только в том случае, если флажок выполнять обратную отправку и автоматическую обратную отправку = true подходит для вас. (если нет, то моя идея не имеет большой ценности).
2. Да , это действительно имеет смысл. Однако у меня есть функция , которая сворачивает и расширяет дочернее представление сетки при нажатии кнопки. Затем, если я поставлю флажок и автоматическая обратная запись будет верна, в дочерней сетке она вернется в исходное состояние, которое «свернуто», и этого не может произойти.
3. Хм, мой опыт показывает, что сетка и расширенная дочерняя сетка не будут колипироваться на обратной стороне. (состояние обоих gv должно оставаться в порядке до тех пор, пока вы не свяжете сетку на этом посту обратно. Я могу опубликовать пример — я часто использую представление списка для родительской сетки, так как оно лучше поддерживает «промежутки», чем использование двух вложенных gv. Я немного позже опубликую свой рабочий пример.
4. Хм , хорошо! Я попробую разобраться с вашим решением. Заранее большое вам спасибо
5. хорошо, опубликовано — обратите внимание, что мы могли бы удалить весь беспорядок (lv) внутри панели обновления, если другие части страницы не справляются или не хотят возвращать сообщение на всю страницу. Разберитесь, как это работает — в нем не слишком много кода, но все это код на стороне сервера. Я полагаю, что было бы неплохо сделать эту работу на стороне клиента, но это не имеет большого значения. Я имею в виду, что если бы я начал писать много JavaScript, то да, это был бы «лучший» ответ, но пока этот подход все еще достаточно отзывчив.
Ответ №1:
Хорошо, во-первых, я собираюсь предложить, чтобы основная сетка представляла собой представление списка.
Причина в том, что listview поддерживает «span» намного лучше. Когда я пытаюсь вложить gv, они, как правило, выглядят так:
Но если вложить представление сетки в представление списка, то оно будет работать намного лучше, как это:
И действительно удивительно, что без дополнительного кода расширенные части сохраняются — на самом деле без какого-либо дополнительного кода.
Итак, вот наша разметка — и я добавил флажок в дочерний gv выше.
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
<ItemTemplate>
<tr style="">
<td><asp:Button ID="cmdView" runat="server" Text=" " OnClick="cmdView_Click" /></td>
<td><asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' /></td>
<td><asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>' /></td>
<td><asp:Label ID="ProvinceLabel" runat="server" Text='<%# Eval("Province") %>' /></td>
<td><asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' /></td>
</tr>
<tr>
<td colspan="5">
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table table-hover" style="display:none" >
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="Firstname" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:CheckBox id="ckSel" runat="server"
OnCheckedChanged="ckSel_CheckedChanged"
AutoPostBack="true" >
</asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" Class = "table table-hover" >
<tr runat="server" style="">
<th runat="server">View</th>
<th runat="server">HotelName</th>
<th runat="server">City</th>
<th runat="server">Province</th>
<th runat="server">Description</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
Хорошо, итак, вот наша загрузка в сетку (ну, я использовал listview).
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
public void LoadGrid()
{
string strSQL = @"SELECT * FROM tblHotels WHERE ID in (select hotel_Id from People)
ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
ListView1.DataSource = cmdSQL.ExecuteReader();
ListView1.DataBind();
}
}
Хорошо, итак, запустите вышесказанное, и мы получим это:
Хорошо, теперь следующая автобусная остановка-клавиша . Это просто обычный самолет Джейн asp.net пуговица. И я НЕ стал заморачиваться с gridview или listview, встроенным в события (выбранный индекс и все такое прочее) — это слишком запутанно, а еще лучше, нам просто все равно и не нужно беспокоиться о событиях этих gv или lv.
Итак, наш код таков: не слишком много!!!
protected void cmdView_Click(object sender, EventArgs e)
{
Button cmd = (Button)sender;
ListViewDataItem gVR = (ListViewDataItem)cmd.Parent;
GridView gChild = (GridView)gVR.FindControl("GridView2"); // pluck out the grid for this row
if (gChild.Style["display"] == "normal")
{
// if grid is already display, then hide it, and exit
gChild.Style["display"] = "none";
return;
}
gChild.Style["display"] = "normal";
string HotelPK = (string)ListView1.DataKeys[gVR.DataItemIndex]["ID"];
// only re-load if never loaded (can't re-load else blow out check boxes
if (gChild.Rows.Count == 0)
{
string strSQL = @"SELECT * from People where hotel_id = " HotelPK;
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
gChild.DataSource = cmdSQL.ExecuteReader();
gChild.DataBind();
}
}
}
Хорошо, так что это будет расширяться, колипазируйте каждую строку. и ДЕЙСТВИТЕЛЬНО удивительно, что управление состоянием работает (оно запоминает расширение или сворачивание — и даже запомнит установку флажка «Не привязано».
Итак, мы расширяем, скажем, первый ряд. Мы получаем это:
Хорошо, теперь осталась только часть-событие щелчка флажка. и опять же, не слишком много кода:
protected void ckSel_CheckedChanged(object sender, EventArgs e)
{
CheckBox ckBox = (CheckBox)sender;
GridView gvChild = (GridView)ckBox.Parent.Parent.Parent.Parent;
GridViewRow gvRowClick = (GridViewRow)ckBox.Parent.Parent;
if (ckBox.Checked)
{
// user just checked this box - un-check all
foreach (GridViewRow gvRow in gvChild.Rows)
{
if (gvRow.RowIndex != gvRowClick.RowIndex)
{
CheckBox ckRowBox = (CheckBox)gvRow.FindControl("ckSel");
ckRowBox.Checked = false;
}
}
}
}
Несколько вещей:
Как уже отмечалось, я отказался от использования модели событий gridv/listv. (мы просто выбираем строку представления сетки/списка, используя sender.parent.
И мы не загружаем дочерние сетки до тех пор, пока они не будут расширены — это хорошо для производительности.
и если он был расширен, и мы снова нажимаем» «, мы скрываемся, но если мы снова развернем, то мы не попадем в базу данных для повторной загрузки (и мы не хотим этого делать, так как если бы мы это сделали, то флажок был бы потерян).
И довольно удивительно? lv/gv сохраняет свое состояние для нас. Таким образом, расширенные части даже поддерживают обратный код для отправки флажка.
Я не записывал обратно в базу данных, но это был бы довольно простой код, чтобы затем обработать каждую строку представления списка, затем получить gv, а затем получить проверенную строку (идентификатор PK), а затем записать ее обратно в базу данных или сделать что угодно, если мы захотим, на какой-нибудь кнопке за пределами этого lv/gv.
Комментарии:
1. Я решил сохранить оба своих представления сетки , событие checkedchanged сработало как заклинание, но, как я и ожидал , с autopostback=»true», дочернее представление сетки мгновенно сворачивается, и вы сами сказали, что если я повторно свяжусь с этим обратным сообщением, оно, несомненно, изменится в исходное состояние, которое «свернуто», я повторно связываюсь в событии под названием OnRowDataBound (), действительно ли мне нужно изменить его на кнопку, затем в событии OnClick я выполняю привязку данных() какой у меня другой вариант здесь? Большое спасибо.
2. Я обнаружил ошибку в вашем коде , если вы развернете все представления и установите в них один флажок, а если вы развернете другое представление и установите другой флажок, флажок предыдущего представления не будет снят.
3. Это работает для меня, и я не вижу этой проблемы. Работает ли для вас только один флажок «Разрешить»? Вы НИКОГДА НЕ выполняете повторную привязку, кроме как при загрузке первой страницы (но опять же, 99% любого кода все равно будет работать ТОЛЬКО так). Обратите внимание, что в моем примере флажок не привязан (в нем нет выражения, задающего текстовое поле. Нет причин привязывать что-либо еще, кроме того, что вам нужно. в моем примере, если я расширяю группу, я могу установить один флажок. Если я проверяю другое, то другое не проверяется. Что касается повторной привязки к базе данных строк? Ну, конечно, тогда вам не нужен код привязки, который у меня есть на expand.
4. Да , я изучил ваш код почти строчка за строчкой и понял эту часть. Часть, которая все испортила,-это переплеты, как ты и сказал.
5. Поэтому я заставил себя вести себя хорошо, используя некоторый jQuery, таким образом, я также изменил кнопку на «минус» при расширении и «плюс» при сворачивании.