有很多方法可以做到这一点。如果您使用 AjaxControlToolKit,他们有一个很棒的弹出扩展器,并且不需要 JavaScript。
然而,最好的选择可能是使用 jQuery.UI。毫无疑问,您的网站和应用程序有 jQuery,所以,我会添加 jQuery.UI。您可以使用 nueget 来安装它,或者直接访问 jquery 站点并下载 jQuery.UI 文件。它们很常见。
因此,我们这样做的方式是您(通常)在页面上创建一个“div”,它是一个弹出窗口。这很有效,因为它对“点击”的响应非常快(您甚至不必点击服务器即可弹出对话框。但是,您弹出的表单可能是用于编辑数据。
下一个考虑是弹出表单不能有回发。 (嗯,好的,它可以有一个)。那么如果你弹出的表单是有一些丰富的验证码,或者需要一些服务器端事件代码才能运行的代码呢?你往往不走运。因此,您可以轻松弹出一个表单,用户可以编辑(或输入数据),但是您只允许一个回发按钮事件(比如“确定 - 保存”)。所以在大多数情况下,这样的弹出表单很好,但请记住这个限制。如果您确实需要在该对话框中做出响应,那么在大多数情况下您必须编写 ajax 调用——这对开发人员来说是额外的痛苦和工作量。
所以,假设我们要弹出一个对话框来过滤网格。弹出窗口将允许用户输入酒店名称的前几个字符,或者我们可以从下拉列表中选择一个城市来按城市过滤网格。
我们在一个只显示“活动”的记录中加入一个复选框。
那么,这将如何工作,看起来如何? (并牢记上述注意事项(弹出对话框中只允许回发一次)。
好吧,我们首先构建网格。但是,我们需要在标题中添加一些按钮。所以我必须删除一些数据绑定字段,并为那一列使用模板。这让我们可以使用按钮或任何我们喜欢的方式设置标题。
我对城市标题做了同样的事情。
所以,我们有这个标记:
<div id="HotelGrid" runat="server" style="width:50%">
<asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-hover"
style="vertical-align:middle" ShowHeaderWhenEmpty="true">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton ID="btnSearchCity"
runat="server"
CssClass="btn-default btn-sm"
>City
<span aria-hidden="true" class="glyphicon glyphicon-search"></span>
</asp:LinkButton>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lblCity" runat="server" Text='<%# Eval("City") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:TemplateField HeaderStyle-Width="200px">
<HeaderTemplate>
<asp:LinkButton ID="cmdSearchHotel"
runat="server"
CssClass="btn-default btn-sm"
OnClientClick="return mysearch(this);"
OnClick="cmdSearchHotel_Click"
>Hotel
<span aria-hidden="true" class="glyphicon glyphicon-search"></span>
</asp:LinkButton>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lblHotel" runat="server" Text='<%# Eval("HotelName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Description"HeaderText="Description" />
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:CheckBox ID="chkActive" runat="server" Checked='<%# Eval("Active") %>' />
</ItemTemplate>
<ItemStyle HorizontalAlign="Center"></ItemStyle</asp:TemplateField>
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"class="btn" OnClick="cmdEdit_Click"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
现在,您可以在上面看到,标记开始增长 - 这是由于 gridview 需要围绕每组控件的“模板”。 (我经常建议使用列表视图,因为您不需要模板。但没什么大不了的。
好的,我们有了上面的标记。
我的页面加载代码来加载网格?好吧,我们希望显示标题,所以我们这样做:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
GHotels.DataSource = MyRst("select * from tblHotels where id = 0")
GHotels.DataBind()
' load the city combo box
cboCity.DataSource = MyRst("SELECT City from tblCity ORDER BY City")
cboCity.DataBind()
cboCity.Items.Insert(0, "") ' allow blank selection
End If
End Sub
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using MyCon As SqlConnection = New SqlConnection(My.Settings.TEST3)
Using cmdSQL As New SqlCommand(strSQL, MyCon)
cmdSQL.Connection.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
好的,所以我们现在看到/有了这个:
现在,网格标题中的两个按钮将有两个部分。
弹出对话框的部分(jQuery.UI),然后是标准代码服务器端。
好的,我们必须创建一个 div 来保存我们的弹出窗口。
它将相当简单,只有组合框(用于城市)、用于酒店名称的文本框和用于“仅活动”过滤器的复选框。
所以,那个 div 很简单。并注意当我们对 div 布局感到满意时,我们添加 display:none 来隐藏 div。
所以我们有这个:
<div id="mysearchdiv" style="border:solid;width:300px;text-align:right;padding:15px;font-size:large;display:NONE">
<p>Select City
<asp:DropDownList ID="cboCity" runat="server" width="150px"
DataTextField="City"
DataValueField="City"
></asp:DropDownList>
</p>
<p>
Hotel Name
<asp:TextBox ID="txtSearchHotel" runat="server" Width="150" Height="25"></asp:TextBox>
</p>
<p>
Include Only Active
<asp:CheckBox ID="chkActiveOnly" runat="server" />
</p>
<asp:HiddenField ID="cmdOption" runat="server" ClientIDMode="Static"/>
</div>
非常简单的标记。
好的,现在最难的部分是,jQuery UI 是一个 java 脚本例程,它是这样的:
<script>
var searchok = false
function mysearch(btn) {
if (searchok) {
return true
}
var myDialog = $("#mysearchdiv");
myDialog.dialog({
title:"Search For Hotels",
modal: true,
width: "320px",
resizable: false,
appendTo: "form",
autoOpen: true,
buttons: {
Ok: function ()
{
searchok = true
btn.click()
},
Clear: function () {
searchok = true
$('#cmdOption').val('c')
btn.click()
},
Cancel: function () {
myDialog.dialog('close')
}
}
});
return false
}
</script>
所以,这是一些代码,但 jQuery.UI 是“抓取”那个 div,并将其转换为一个漂亮的对话框。所以最终的结果是这样的:
现在,要么是在我开始输入后添加了 c# 标签,要么我错过了它。
但是,c# 代码大致相同。第一个页面加载代码是这样的:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GHotels.DataSource = MyRst("select * from tblHotels where id = 0");
GHotels.DataBind();
// load our search combo box
cboCity.DataSource = MyRst("SELECT City from tblCity ORDER BY City");
cboCity.DataBind();
cboCity.Items.Insert(0,new ListItem("",""));
}
}
public DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST3)))
{
cmdSQL.Connection.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
return rstData;
}
所以上面会加载网格(我们发送一个空白行,因为我们使用标题进行搜索。
然后按钮点击?好吧,我们弹出一个 jquery 对话框。如果它返回 true 或 false - 这将确定服务器端按钮是否会触发。
所以,我们有这个:
<asp:TemplateField HeaderStyle-Width="200px">
<HeaderTemplate>
<asp:LinkButton ID="cmdSearchHotel"
runat="server"
CssClass="btn-default btn-sm"
OnClientClick="return mysearch(this);"
OnClick="cmdSearchHotel_Click"
>Hotel
<span aria-hidden="true" class="glyphicon glyphicon-search"></span>
</asp:LinkButton>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lblHotel" runat="server" Text='<%# Eval("HotelName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
请注意我们如何让 jQuery 搜索例程返回 true 或 false。
好的,现在编写该代码以根据该弹出窗口过滤/搜索网格是一件简单的事情。
代码很简单,我们将每个搜索选项“累积”加起来,如果搜索框中没有输入值,则直接跳过选项。
而且,我们添加了该隐藏字段,因为正如您所见,我们现在可以向该对话框添加更多按钮,但不必创建新的代码服务器端 - 只需单击一个按钮即可处理所有选项对话框。
这个过滤的c#代码是这样的:
protected void cmdSearchHotel_Click(object sender, EventArgs e)
{
if (cmdOption.Value == "c")
{
// clear the search option
cboCity.Text = "";
txtSearchHotel.Text = "";
chkActiveOnly.Checked = false;
cmdOption.Value = "";
GHotels.DataSource = MyRst("select * from tblHotels where id = 0");
GHotels.DataBind();
return;
}
// filter the grid
string strWhere = "";
using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST3))
using (SqlCommand cmdSQL = new SqlCommand("SELECT * FROM tblHotels",con))
{
if (cboCity.Text != "")
{
strWhere += "City = @City";
cmdSQL.Parameters.Add("@City", SqlDbType.NVarChar).Value = cboCity.Text;
}
if (txtSearchHotel.Text != "")
{
if (strWhere != "")
strWhere += " AND ";
strWhere += "HotelName like @Hotel + '%'";
cmdSQL.Parameters.Add("@Hotel", SqlDbType.NVarChar).Value = txtSearchHotel.Text;
}
if (chkActiveOnly.Checked)
{
if (strWhere != "")
strWhere += " AND ";
strWhere += "Active = 1";
}
if (strWhere != "")
cmdSQL.CommandText += " WHERE " + strWhere;
cmdSQL.CommandText += " ORDER BY HotelName";
con.Open();
GHotels.DataSource = cmdSQL.ExecuteReader();
GHotels.DataBind();
}
所以,总而言之:
绝对最少的代码。
与典型的网格相比,标记并不多。
我还分享了一个很长时间以来极少数人使用过的超酷技巧。如果我们不想,这就是如何让一个 jQuery.UI 对话框不触发服务器端按钮。因此我们在java中不需要多个例程,我们也不需要服务器端的多个例程。我们只需要一个按钮调用对话框,它会返回 true 或 false。但它仍然像所有和大多数 JavaScript 小部件一样运行异步。 (不允许使用阻塞代码!!!)。