我想实现如果复选框被选中或取消选中,提示确认消息。之后仅执行代码隐藏逻辑来更新数据库。但后来我意识到 __doPostBack 无法访问 GV_SplitPaymentOption_RowCommand 函数。这是为什么?
据我研究,CheckBox 控件本身并不支持 CommandName 和 CommandArgument,但 __doPostBack 函数仍然可以与 CheckBox 控件一起使用,以使用附加参数启动回发。所以不确定我遗漏或错误了哪一部分。任何专家都可以提供帮助,因为我已经坚持了很长时间了。
<script type="text/javascript">
function confirmCheckBoxChange(checkbox) {
var currentChecked = checkbox.checked;
var row = checkbox.closest("tr");
var message = currentChecked ? "Are you sure you want to activate?" : "Are you sure you want to deactivate?";
if (!confirm(message)) {
return false;
}
__doPostBack(checkbox.id);
return true;
}
</script>
<asp:GridView ID="GV_Member" runat="server" Width="100%" AutoGenerateColumns="False"
OnRowDataBound="GV_Member_RowDataBound" OnRowCommand="GV_Member_RowCommand">
<Columns>
<asp:TemplateField HeaderText="No">
<ItemTemplate>
<asp:Label ID="lblNo" runat="server" Text='<%# Container.DataItemIndex + 1 %>' Visible="true"></asp:Label>
</ItemTemplate>
<HeaderStyle HorizontalAlign="CENTER" Width="20" />
<ItemStyle HorizontalAlign="LEFT" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:Label ID="lblName" runat="server" Text='<%# Bind("Name") %>'></asp:Label>
</ItemTemplate>
<HeaderStyle HorizontalAlign="CENTER" />
<ItemStyle HorizontalAlign="CENTER" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Active" HeaderStyle-Width="10%" ItemStyle-Width="10%">
<ItemTemplate>
<label class="switch" style="margin-left: 5px;">
<asp:CheckBox ID="chkActive" runat="server" Checked='<%# Bind("Active") %>' CommandName="UpdateActive" onclick="confirmCheckBoxChange(this);" AutoPostBack="false" CommandArgument='<%# Eval("Gender") + "&" + Eval("BirthCode") + "&" + Eval("Address")%>' />
<span class="slider round"></span>
</label>
<asp:Label ID="lblBVStatus" runat="server" Text='<%# Convert.ToBoolean(Eval("Active")) ? "Activate" : "Deactivate" %>' Visible="true" Style="margin-left: 5px;"></asp:Label>
</ItemTemplate>
<HeaderStyle HorizontalAlign="CENTER" />
<%--<ItemStyle HorizontalAlign="CENTER" />--%>
</asp:TemplateField>
</Columns>
</asp:GridView>
这里没有真正需要使用 row 命令。
在任何 GridView、ListView 或其他什么中?
您可以放入标准按钮、复选框、下拉列表或其他任何内容,然后只需使用该给定控件的标准事件即可。
但是,请记住,当您有一个自动回发 = true 的复选框,并且同时具有客户端单击事件和服务器端事件时?
与按钮不同,对于复选框,自动回发代码和单击事件“组合”为一次单击事件。
这意味着您的客户端点击事件必须考虑到上述情况,并且点击表达式必须以这样的方式编写:如果js代码返回true,则代码继续。
此示例显示了所需的设置:
<asp:CheckBox ID="chk1" runat="server" Text="Check me"
OnCheckedChanged="chk1_CheckedChanged"
AutoPostBack="true"
onclick="if (!confirmCheckBoxChange(this)) {return false};"
/>
<script>
function confirmCheckBoxChange(chkbox) {
var message = chkbox.checked ? "Are you sure you want to activate?"
: "Are you sure you want to deactivate?";
if (!confirm(message)) {
return false;
}
return true;
}
</script>
因此,在上面,我们既有服务器端单击事件,又有客户端单击事件。通过复选框,这两个事件将合并为一个客户端单击事件,因此请注意我如何更改客户端单击事件以“继续”客户端单击 js 代码后面的注入代码。
所以,使用这种格式:
"if (!confirmCheckBoxChange(this)) {return false};"
与使用此相反:
"return confirmCheckBoxChange(this)"
因此,请记住上面的返回 true,然后我们希望 asp.net 服务器端表达式(由 asp.net 注入)在函数返回 true 时运行。
那么,下一个问题当然是我们关心,或者必须担心,还是使用GridView的命令方法?或者有没有更好的方法来获取当前的GridView?
答案是肯定的,因此人们会发现最好忽略并且不使用 GridView 命令事件。
事实上,建议大多数情况下您不要理会 GridView(或 ListView 等)的命令事件。
从那时起,每个控件都可以有自己的独立事件存根(按钮、组合框、复选框等),这样您就不必将多个控件的一大堆代码放入该命令的一个命令事件中网格视图。
结果是为相关控件提供了一组非常易于使用的标准事件。
因此,假设我们将复选框设置为 auto-post back = true,那么我们可以使用按钮、复选框等的“长时间”功能,当客户端例程返回 true 时,服务器端代码运行。如果我们返回 false,则客户端事件不会运行。
因此,现在有了上述信息,这是一个基于上述概念的工作 GridView。
<asp:GridView ID="GVHotels" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table table-hover"
Width="45%">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Active"
ItemStyle-HorizontalAlign="Center"
HeaderStyle-HorizontalAlign="Center" ItemStyle-Width="120px">
<ItemTemplate>
<asp:CheckBox ID="chk1" runat="server"
Checked='<%# Eval("Active")%>'
OnCheckedChanged="chk1_CheckedChanged"
AutoPostBack="true"
onclick="if (!confirmCheckBoxChange(this)) {return false};" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<script>
function confirmCheckBoxChange(chkbox) {
var message = chkbox.checked ? "Are you sure you want to activate?"
: "Are you sure you want to deactivate?";
if (!confirm(message)) {
return false;
}
return true;
}
</script>
请注意我们如何仅使用复选框的“常规”事件以及 autopostback=“true”来运行服务器端代码。
背后代码:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
string strSQL = @"SELECT * FROM tblhotelsA
ORDER BY HotelName";
GVHotels.DataSource = General.MyRst(strSQL);
GVHotels.DataBind();
}
protected void chk1_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
GridViewRow gRow = (GridViewRow)chk.NamingContainer;
Debug.Print($"check box checked = {chk.Checked}");
Debug.Print($"Row index click = {gRow.RowIndex}");
int PK = (int)GVHotels.DataKeys[gRow.RowIndex]["ID"];
Debug.Print($"Data base PK value = {PK}");
// get Hotel Name from Grid view row
Debug.Print($"Hotel Name = {gRow.Cells[3].Text}");
}
结果是这样的:
调试输出:
check box checked = False
Row index click = 1
Data base PK value = 10
Hotel Name = Canadian Rocky Mountain Resorts
因此,如上所示,我们可以轻松获取单击的行,并从中使用行索引、数据库 PK 行 ID(数据键),当然还有复选框的状态。因此,不需要使用命令对象或内置的 GridView 事件。