【发布时间】:2014-03-04 12:29:45
【问题描述】:
我有一个带有下拉值的网格视图和一个页面中的更新按钮。每当用户更改下拉列表中的任何值并尝试离开页面(分页)时,都会弹出确认警报。如果他们单击“确定”,则必须导航到选定的索引页面,如果单击“取消”,则必须保持在同一页面上。无论如何我可以跟踪更改的单元格值并在用户尝试进行分页或移动到另一个页面而不单击页面中的更新按钮时发出警报。
关于如何实现这一点的任何建议。
【问题讨论】:
我有一个带有下拉值的网格视图和一个页面中的更新按钮。每当用户更改下拉列表中的任何值并尝试离开页面(分页)时,都会弹出确认警报。如果他们单击“确定”,则必须导航到选定的索引页面,如果单击“取消”,则必须保持在同一页面上。无论如何我可以跟踪更改的单元格值并在用户尝试进行分页或移动到另一个页面而不单击页面中的更新按钮时发出警报。
关于如何实现这一点的任何建议。
【问题讨论】:
您可以使用此链接 here 在 gridview 中添加下拉菜单,并在下拉菜单的更改事件中添加 boolean 值到 viewstate 变量,例如
ViewState["IsDDChanged"] = true;
然后您可以注册gridview的PageIndexChanging事件并检查viewstate中的值是否为真,然后您可以使用“RegisterStartupScript”或“RegisterClientScriptBlock”注册一个javascript。关于如何注册 javascript 的链接是 here。
注册 javascript 后,您可以在同一事件中或通过上述已注册 javascript 的 ajax 调用将 viewstate 设置为 false,具体取决于您的要求。这对于它下次工作很重要。您甚至可以取消分页事件。此链接here
中给出了该事件和一个很好的例子这些可能会给你一个很好的方向。
希望这会有所帮助。
编辑:
我手头有一些时间,所以为您完成了这个小型 POC。 将 aspx 和 aspx.cs 代码复制到一个单独的项目中,并检查这是否是您所需要的
以下是我遵循的步骤
RowCreated 事件并使用它添加了下拉列表PageIndexChanging 事件并使用ScriptManager.RegisterStartupScript 注册了javascript
有几点我做过,你需要记住
@Page 指令中,我给出了EnableEventValidation="false"。这是必需的,以便我可以触发隐藏按钮的单击事件,但这不是一个好习惯,因为它会降低安全性。对于更安全的方式,您应该使用UpdatePanel of AJAX extensions。AutoPostBack 到 true 的下拉列表非常重要,否则您的 selectedIndexChanged 事件将不会被触发。即ddlDesignation.AutoPostBack = true;
aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Grid_Practice.aspx.cs" EnableEventValidation="false" Inherits="Practice_Web.Grid_Practice" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title> <script type="text/javascript" language="javascript"> function ConfirmUser(msg) { if (confirm(msg)) { __doPostBack('Button1', 'OnClick'); } } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true" runat="server"> </asp:ScriptManager> <div> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" Style="display: none;" /> <asp:GridView ID="GridView1" runat="server" OnPageIndexChanging="GridView1_PageIndexChanging" AllowPaging="true" PageSize="10" AutoGenerateColumns="false" OnRowCreated="GridView1_RowCreated"> <PagerSettings Mode="NextPreviousFirstLast" FirstPageText="First" LastPageText="Last" NextPageText="Next" PreviousPageText="Prev" Position="TopAndBottom" /> <Columns> <asp:BoundField /> </Columns> </asp:GridView> </div> </form> </body> </html>
aspx.cs
namespace Practice_Web
{
public partial class Grid_Practice : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Dummy value for gridview
DataTable dt1 = new DataTable();
dt1.Columns.Add(new DataColumn("Designation", typeof(String)));
DataRow dr = null;
for (int i = 0; i < 15; i++)
{
dr = dt1.NewRow();
dr[0] = "designation" + (i % 2);
dt1.Rows.Add(dr);
}
Session["dt"] = dt1;
GridView1.DataSource = dt1;
GridView1.DataBind();
}
}
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
Session["NewPageIndex"] = e.NewPageIndex;
var sessionVar = Session["dropdownChanged"];
bool dropdownChanged = false;
if (sessionVar != null)
dropdownChanged = Convert.ToBoolean(Session["dropdownChanged"]);
if (dropdownChanged)
{
ScriptManager.RegisterStartupScript(this, typeof(string), "Error", "ConfirmUser('Are u sure');", true);
}
else
{
ChangeGridPage();
}
}
public void ChangeGridPage()
{
int pageIndex = Convert.ToInt32(Session["NewPageIndex"]);
GridView1.PageIndex = pageIndex;
GridView1.DataSource = (Session["dt"] as DataTable);
GridView1.DataBind();
}
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddlDesignation = new DropDownList();
ddlDesignation.SelectedIndexChanged += new EventHandler(ddlDesignation_SelectedIndexChanged);
ddlDesignation.AutoPostBack = true;
ddlDesignation.ID = "MyID" + e.Row.RowIndex.ToString();
DataTable dt1 = new DataTable();
dt1.Columns.Add(new DataColumn("Designation", typeof(String)));
DataRow dr = null;
dr = dt1.NewRow();
dr[0] = "designation0";
dt1.Rows.Add(dr);
dr = dt1.NewRow();
dr[0] = "designation1";
dt1.Rows.Add(dr);
ddlDesignation.DataSource = dt1;
ddlDesignation.DataTextField = "Designation";
ddlDesignation.DataValueField = "Designation";
ddlDesignation.DataBind();
ddlDesignation.Items.Insert(0, new ListItem("--Select--", "0"));
ddlDesignation.SelectedValue = (Session["dt"] as DataTable).Rows[e.Row.RowIndex][0].ToString();
e.Row.Cells[0].Controls.Add(ddlDesignation);
}
}
void ddlDesignation_SelectedIndexChanged(object sender, EventArgs e)
{
Session["dropdownChanged"] = true;
//other code here
}
protected void Button1_Click(object sender, EventArgs e)
{
ChangeGridPage();
}
}
}
希望这能解决您的问题
【讨论】:
这似乎是一个很长的答案,但它非常容易应用。
作为此方案的临时(替代但有效)解决方案,我在MSDN 中找到了这篇关于创建您自己为 GridView 创建 PagerTemplate 的文章。分页器会在 DropDownList 中,它很有趣,并且会更灵活地实现您的要求,为了达到要求,我在代码中稍作修改。
在您的标记中,将 GridView 修改为如下所示:
<asp:GridView ID="gridUsers" runat="server" ShowHeaderWhenEmpty="true" AutoGenerateColumns="False"
OnDataBound="CustomersGridView_DataBound"
HorizontalAlign="Center" Width="100%" AllowPaging="True" >
<pagerstyle forecolor="Blue"
backcolor="LightBlue"/>
<PagerTemplate>
<table width="100%">
<tr>
<td style="width:70%">
<asp:label id="MessageLabel"
forecolor="Blue"
text="Select a page:"
runat="server"/>
<asp:dropdownlist id="PageDropDownList"
onselectedindexchanged="PageDropDownList_SelectedIndexChanged"
AutoPostBack="true"
onChange="if(!confirm('Continue without saving?! Data will be lost!'))return false;"
runat="server"/>
</td>
<td style="width:70%; text-align:right">
<asp:label id="CurrentPageLabel"
forecolor="Blue"
runat="server"/>
</td>
</tr>
</table>
</PagerTemplate>
<Columns>
<!-- columns -->
</Columns>
</asp:GridView>
接下来,添加如下函数(我用的是VB.Net):
Protected Sub PageDropDownList_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
' Retrieve the pager row.
Dim pagerRow As GridViewRow = gridUsers.BottomPagerRow
'Retrieve the PageDropDownList DropDownList from the bottom pager row.
Dim pageList As DropDownList = DirectCast(pagerRow.Cells(0).FindControl("PageDropDownList"), DropDownList)
' Set the PageIndex property to display that page selected by the user.
gridUsers.PageIndex = pageList.SelectedIndex
SelectData()
End Sub
最后添加如下函数:
Protected Sub CustomersGridView_DataBound(ByVal sender As Object, ByVal e As System.EventArgs)
' Retrieve the pager row.
Dim pagerRow As GridViewRow = gridUsers.BottomPagerRow
'Retrieve the PageDropDownList DropDownList from the bottom pager row.
Dim pageList As DropDownList = DirectCast(pagerRow.Cells(0).FindControl("PageDropDownList"), DropDownList)
Dim pageLabel As Label = DirectCast(pagerRow.Cells(0).FindControl("CurrentPageLabel"), Label)
If pageList IsNot Nothing Then
For i As Integer = 0 To gridUsers.PageCount
Dim pageNumber As Integer = i + 1
Dim item As New ListItem(pageNumber.ToString())
If i = gridUsers.PageIndex Then
item.Selected = True
End If
pageList.Items.Add(item)
Next
End If
If pageLabel IsNot Nothing Then
Dim currentPage As Integer = gridUsers.PageIndex + 1
pageLabel.Text = "Page " + currentPage.ToString() + " of " + gridUsers.PageCount.ToString()
End If
End Sub
我确信这不是最好的解决方案,但它很有趣。请注意,我修改了 DropDownList 设计并添加了“OnChange”事件,该事件将执行客户端警报技巧。
但是,如果用户取消回发,您还需要弄清楚在 DropDownList 中返回旧页码的另一件事,我想您只需创建一个 javascript 函数即可以某种方式实现这一目标。
希望这会有所帮助。
【讨论】: