支持行单击、双击事件的GridView和DataList控件(译)
支持行单击、双击事件的GridView和DataList控件(译)
介绍
背景
GridView中的单击和双击
创建一个包含默认页的web应用程序。然后,在页面的Page指令中添加EnableEventValidation ="false"。稍后我们会将其删除。添加 GridView 并绑定一些数据。添加两个使用 GridView 编辑列选项的asp: ButtonField 控件。给这两个ButtonField的CommandName分别命名为SingleClick、DoubleClick 。(选择按钮也可以用于 SingleClick 事件但我已经决定两个都用 asp: ButtonField)。
<Columns>
<asp:ButtonField Text="SingleClick" CommandName="SingleClick" />
<asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" />
</Columns>
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
GridView _gridView = (GridView)sender; // Get the selected index and the command name
int _selectedIndex = int.Parse(e.CommandArgument.ToString());
string _commandName = e.CommandName; switch (_commandName)
{
case ("SingleClick"):
_gridView.SelectedIndex = _selectedIndex;
this.Message.Text += "Single clicked GridView row at index "
+ _selectedIndex.ToString() + "<br />";
break;
case ("DoubleClick"):
this.Message.Text += "Double clicked GridView row at index "
+ _selectedIndex.ToString() + "<br />";
break;
}
}
创建一个RowDataBound 事件去修改绑定的每一行。现在,我们需要得到 SingleClick 按钮用于回发的客户端脚本并将其分配到整行。
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the LinkButton control in the first cell
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsSingle =
ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
// Add this javascript to the onclick Attribute of the row
e.Row.Attributes["onclick"] = _jsSingle;
}
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the LinkButton control in the second cell
LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsDouble =
ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
// Add this JavaScript to the ondblclick Attribute of the row
e.Row.Attributes["ondblclick"] = _jsDouble;
}
如果我们同时实现了上面两个事件,在功能上只会响应单击事件。这是因为当用户双击时,他的第一次点击被识别为单击然后页面在双击事件响应前就回传了。JavaScript的setTimeOut方法可以用来给单击事件设置一个延迟,从而给用户一个机会去完成双击操作。通过查看页面源码,我们可以发现OnClick事件在tr标签内:
onclick="javascript:__doPostBack('GridView1$ctl02$ctl00','')"
添加一个setTimeout方法,并为其设置300毫秒延迟:
onclick="javascript:setTimeout("__doPostBack('GridView1$ctl02$ctl00','')",300)"
于是完整的RowDataBound代码如下:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the LinkButton control in the first cell
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsSingle =
ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
// To prevent the first click from posting back immediately
// (therefore giving the user a chance to double click)
// pause the postbackfor 300 milliseconds by
// wrapping the postback command in a setTimeout
_jsSingle = _jsSingle.Insert(, "setTimeout(\"");
_jsSingle += "\", 300)";
// Add this javascript to the onclick Attribute of the row
e.Row.Attributes["onclick"] = _jsSingle; // Get the LinkButton control in the second cell
LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsDouble =
ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
// Add this javascript to the ondblclick Attribute of the row
e.Row.Attributes["ondblclick"] = _jsDouble;
}
}
这两个按钮也无需再显示,设置其Visible="false":
<Columns>
<asp:ButtonField Text="SingleClick" CommandName="SingleClick" Visible="false" />
<asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" Visible="false" />
</Columns>
现在RowCommand代码就能正确捕获和处理行单击和双击了。
注册用于验证的回发、回调数据
一切工作正常,但请记住,我们一开始在页面指令中添加了 EnableEventValidation ="flase"。这并不是最安全的选项,所以我们应该将其删除。但这将导致行单击或双击时触发"回发、回调参数无效"错误。错误提示告诉我们可以通过ClientScriptManager.RegisterForEventValidation来注册用于验证的回发、回调数据。(至于EventValidation 的目的已在别的文章里写得很详尽了本文不予赘述)。
protected override void Render(HtmlTextWriter writer)
{
foreach (GridViewRow r in GridView1.Rows)
{
if (r.RowType == DataControlRowType.DataRow)
{
Page.ClientScript.RegisterForEventValidation
(r.UniqueID + "$ctl00");
Page.ClientScript.RegisterForEventValidation
(r.UniqueID + "$ctl01");
}
}
base.Render(writer);
}
至此,我们将不会再遇到"Invalid postback or callback argument" 错误。
其它控件
在源代码中,我还演示了如何在DataList和ListBox中实现此功能。代码基本相同所以我就不贴在这里了。
DataList中实现行单击、双击
ListBox中实现行单击、双击
在ListBox中,它本身是没有Row或Item事件的,但onclick 和ondblclick 属性可以添加到控件中去。在SelectedIndexChanged事件处理程序中,通过Request.Form["__EventArgument"] 获取命令名。
结论
通过查看由 ASP.NET 生成的 javascript 代码,我们可以扩展 GridView 和 DataList 控件的功能。为了保护你的应用程序安全,您应该尽量避免使用 EnableEventValidation ="false"。一旦你理解了 EventValidation 的工作原理,你可以通过 ClientScript.RegisterForEventValidation 来确保您的代码按预期方式工作。
源码下载地址
https://yunpan.cn/cYTKyZFjQuS2c 访问密码 036e (不嫌麻烦的话,最好前往原文地址下载)
Clickable and Double Clickable Rows with GridView and DataList Controls (ASP.NET 2.0)
Introduction
There are several online sources describing how to make a GridView
row clickable anywhere on the row. There are also a few which describe how to make a row double-clickable. I haven't come across any which handle both events or deal with event validation errors in ASP.NET 2.0.
Here I will describe how to handle single and double clicks with the GridView
, DataList
and ListBox
controls. I will also show how to deal with event validation without disabling it.
Background
While developing an ASP.NET application to replace an old Windows application, I was asked to keep the user experience relatively close to the original. The original application let a user select a row and perform an action on that row from a toolbar. By double clicking on a row the user could open another form with a details view of that row. This type of functionality could easily be achieved with two separate buttons on each row of a GridView
but I needed something better than that.
Single and Double Clicking with a GridView
Create an new web application with a default page. For now, add EnableEventValidation="false"
to the page directive. We will remove it later. Add a GridView
and bind some data to it. Add two asp:ButtonField
controls using the edit columns option on the GridView
. Give these button fields command names of SingleClick
and DoubleClick
. (A select button could also be used for the SingleClick
event but I've decided to use asp:ButtonField
for both.)
<Columns>
<asp:ButtonField Text="SingleClick" CommandName="SingleClick" />
<asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" />
</Columns>
Create a RowCommand
event for the GridView
with a switch
block to capture the separate events.
For the demo, this code will write out a history of the events fired. The SingleClick
command will also set the SelectedIndex
of the row.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
GridView _gridView = (GridView)sender; // Get the selected index and the command name
int _selectedIndex = int.Parse(e.CommandArgument.ToString());
string _commandName = e.CommandName; switch (_commandName)
{
case ("SingleClick"):
_gridView.SelectedIndex = _selectedIndex;
this.Message.Text += "Single clicked GridView row at index "
+ _selectedIndex.ToString() + "<br />";
break;
case ("DoubleClick"):
this.Message.Text += "Double clicked GridView row at index "
+ _selectedIndex.ToString() + "<br />";
break;
}
}
create a RowDataBound
event to modify each row as it is bound. Now we need to take the client script which is used by the SingleClick
button for postback and assign it to the entire row.
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the LinkButton control in the first cell
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsSingle =
ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
// Add this javascript to the onclick Attribute of the row
e.Row.Attributes["onclick"] = _jsSingle;
}
DoubleClick
button, however both of these will not work together.if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the LinkButton control in the second cell
LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsDouble =
ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
// Add this JavaScript to the ondblclick Attribute of the row
e.Row.Attributes["ondblclick"] = _jsDouble;
}
If we implement both these events together we will only get the functionality of the single click.
This is because when the user starts a double click, the first click is taken as a single click and the page is posted back before the second click can happen.
The JavaScript setTimeout
method can be used to set a timeout on the first click, therefore giving the user a chance to complete a double click.
Looking at the source of the page, we can see the onclick
event on the <tr>
tags:
onclick="javascript:__doPostBack('GridView1$ctl02$ctl00','')"
Add a setTimeout
method and give it a timeout of 300 milliseconds:
onclick="javascript:setTimeout("__doPostBack('GridView1$ctl02$ctl00','')", 300)"
So the entire RowDataBound
code looks like:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the LinkButton control in the first cell
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsSingle =
ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
// To prevent the first click from posting back immediately
// (therefore giving the user a chance to double click)
// pause the postbackfor 300 milliseconds by
// wrapping the postback command in a setTimeout
_jsSingle = _jsSingle.Insert(, "setTimeout(\"");
_jsSingle += "\", 300)";
// Add this javascript to the onclick Attribute of the row
e.Row.Attributes["onclick"] = _jsSingle;
// Get the LinkButton control in the second cell
LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[].Controls[];
// Get the javascript which is assigned to this LinkButton
string _jsDouble =
ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
// Add this javascript to the ondblclick Attribute of the row
e.Row.Attributes["ondblclick"] = _jsDouble;
}
}
The buttons no longer need to be visible so hide them by adding Visible="false"
:
<Columns>
<asp:ButtonField Text="SingleClick" CommandName="SingleClick" Visible="false" />
<asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" Visible="false" />
</Columns>
We can now single click and double click on a row and the appropriate action will be captured in the RowCommand
code.
Register the postback or callback data for validation
Everything is working fine, but remember that we added EnableEventValidation="false"
to the page directive. This is not the most secure option so we should remove it. This will cause an "Invalid postback or callback argument" error when a row is clicked or double clicked. The error tells us to use the ClientScriptManager.RegisterForEventValidation
method in order to register the postback or callback data for validation. (The purpose of EventValidation
is well documented elsewhere and beyond the scope of this article.)
The ClientScriptManager.RegisterForEventValidation
can be called by overriding the Render
method. The trick here is to register the unique id of both the buttons for each row of the GridView
. The UniqueID
of the row is returned by GridViewRow.UniqueID
. The UniqueID
of the first button can be generated by appending "$ctl00
" to the row's UniqueID
and for the second button append "$ctl01
".
The overridden Render
method is as follows:
protected override void Render(HtmlTextWriter writer)
{
foreach (GridViewRow r in GridView1.Rows)
{
if (r.RowType == DataControlRowType.DataRow)
{
Page.ClientScript.RegisterForEventValidation
(r.UniqueID + "$ctl00");
Page.ClientScript.RegisterForEventValidation
(r.UniqueID + "$ctl01");
}
}
base.Render(writer);
}
Now we will not get any "Invalid postback or callback argument" errors.
Other Controls
In the source code, I also demonstrate how to achieve this functionality with a DataList
and ListBox
controls. The code is quite similar so I won't show it here.
Single and Double Clicking with a DataList
With the DataList
, the contents of the ItemTemplate
are wrapped in an asp:Panel
, giving something to assign the onclick
and ondblclick
events to.
Single and Double Clicking with a ListBox
With the ListBox
, there are no Row or Item events but the onclick
and ondblclick
attributes can be added to the control.
In the SelectedIndexChanged
event handler, Request.Form["__EventArgument"]
will return the command name.
Conclusion
By looking closely at the JavaScript which is written out by ASP.NET we can extend the functionality of the GridView
and DataList
controls. To keep your applications secure, you should not use EnableEventValidation="false"
if at all possible. Once you understand how EventValidation
works, you can use ClientScript.RegisterForEventValidation
to ensure your code works as intended.
History
- v1.0 - 23rd Sep 2006
- v1.1 - 25th Sep 2006
- v1.2 - 12th Nov 2006
Addition of aListBox
control to the demo - v1.3 - 20th Dec 2006
VB.NET version of demo added to download
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
支持行单击、双击事件的GridView和DataList控件(译)的更多相关文章
- .net dataGridView当鼠标经过时当前行背景色变色;然后【给GridView增加单击行事件,并获取单击行的数据填充到页面中的控件中】
1.首先在前台dataGridview属性中增加onRowDataBound属性事件 2.然后在后台Observing_RowDataBound事件中增加代码 protected void Obser ...
- GridView控件 Reapter控件 DataList控件 的区别和用法
ASP.NET三大控件: 1.GridView控件:表格视图控件,可以用来绑定结果集或者视图,用起来比较方便和灵活,三个控件中使用最多的控件 用法--- this.gridview1.DataSour ...
- java笔记--使用事件分配线程更新Swing控件
使用事件分配线程更新Swing控件: Swing并不是线程安全的,如果在多个线程中更新Swing控件,则很可能造成程序崩溃. 为了避免这种问题,可以使用时间分配线程来更新Swing控件. EventQ ...
- Anroid关于fragment控件设置长按事件无法弹出Popupwindows控件问题解决记录
一.问题描述 记录一下最近在安卓的gragment控件中设置长按事件遇见的一个坑!!! 在正常的activity中整个活动中设置长按事件我通常实例化根部局,例如LinearLayout ...
- MVC中使用Echart后台加载数据 实现饼图、折线图、全国地图数据,单击双击事件等
@{ Layout = null; } @if (false) { <script src="~/Js/jquery-easyui-1.5/jquery.min.js"> ...
- electron 系统托盘 单击 双击事件冲突解决方法
部分代码 // 任务栏点击事件 let timeCount = 0 tray.on('click', function (Event) { setTimeout(() => { if (time ...
- Android入门之GridView(表格控件)
GridView是一个表格控件,可以在每个单元格中显示自定义的View或者字符串.在这里我们要实现一个图标下方有文字的效果. 1.首先我们应自定义布局文件image_text.xml.代码如下: &l ...
- gridview里找到控件
; i < gvIncomeYG.Rows.Count; i++) { Label lblYG_DYYGSR_BHS = ((Label)gvIncomeYG.Rows[i].Cells[].F ...
- 安卓中的事件分发机制之View控件
前言:Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent e ...
随机推荐
- verilog实验3:AD转换后串口输出到PC端
一.实验任务 通过tcl549AD转换芯片将模拟电压信号转换为数字信号,并通过串口显示到电脑上.此AD转换芯片为串行转换芯片,且转换速率要和串口选择的速率匹配.等待串口发送完后,再进行下一次AD转换. ...
- php.ini 中文详解
[PHP] ; PHP还是一个不断发展的工具,其功能还在不断地删减 ; 而php.ini的设置更改可以反映出相当的变化, ; 在使用新的PHP版本前,研究一下php.ini会有好处的 ;;; ...
- Spring基础篇——通过Java注解和XML配置装配bean
自动化装配的确有很大的便利性,但是却并不能适用在所有的应用场景,比如需要装配的组件类不是由自己的应用程序维护,而是引用了第三方的类库,这个时候自动装配便无法实现,Spring对此也提供了相应的解决方案 ...
- CentOS安装JDK 8
准备工作 首先,更新包: yum update 检查服务器上是否已安装旧版本的Java: java -version 如果有旧版本的Java则移除: yum remove java-1.6.0-ope ...
- spring-boot-starter家族成员简介
应用程序starters 以下应用程序starters是Spring Boot在org.springframework.boot组下提供的: springboot使用指南https://docs.sp ...
- 本博客由CSDN迁移而来,显示不正常的博文会慢慢修复!
如题,原博客地址http://blog.csdn.net/vicjiao
- BZOJ3223/洛谷P3391 - 文艺平衡树
BZOJ链接 洛谷链接 题意 模板题啦~2 代码 //文艺平衡树 #include <cstdio> #include <algorithm> using namespace ...
- 在SpringBoot中使用FluentValidator验证插件
前言 在我们编写项目的时候,在controller中往往离不开对一些数据的校验.这里并不是说对于这些数据业务上面的校验,而是对这些数据进行空校验或者是长度校验等. 有些时候校验可以省略,根据业务的需要 ...
- spring cloud熔断监控Hystrix Dashboard和Turbine
参考: http://blog.csdn.net/ityouknow/article/details/72625646 完整pom <?xml version="1.0" e ...
- Redis进阶实践之十四 Redis-cli命令行工具使用详解第一部分
一.介绍 redis学了有一段时间了,以前都是看视频,看教程,很少看官方的东西.现在redis的东西要看的都差不多看完了.网上的东西也不多了.剩下来就看看官网的东西吧,一遍翻译,一遍测试. ...