标签:回发事件 ipostbackeventhandle 服务器控件
在使用Grid的时候,会用到链接跳转。如果只是普通的链接跳转,那只要使用a标签的href就可以实现。但是有时,我们希望在链接跳转的时候,能够引发回发事件,在后台作出一定的处理,然后再跳转。这样要如何实现呢?我们可以定义一个LinkButtonField来实现。代码如下
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.UI; namespace AspNetServerControl { /// <summary> /// 表格链接按钮列 /// </summary> [ToolboxItem(false)] [ParseChildren(true)] [PersistChildren(false)] public class LinkButtonField : BaseField { } }
注:LinkButtonField也是继承自BaseField。添加了一个列字段后,我们就需要在列编辑器中,增加相应的类型,代码如下:
[Designer("AspNetServerControl.Design.GridDesigner, AspNetServerControl.Design")] [ToolboxData("<{0}:Grid Title=\"Grid\" runat=\"server\"><Columns></Columns></{0}:Grid>")] [ToolboxBitmap(typeof(Grid), "toolbox.Grid.bmp")] [Description("表格控件")] [ParseChildren(true)] [PersistChildren(false)] [ControlBuilder(typeof(NotAllowWhitespaceLiteralsBuilder))] [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] public class Grid : ControlBase, IPostBackEventHandler { ///属性代码请参照《 Asp.Net服务器控件开发的Grid实现(二)Html标记渲染》 #region 事件 #region OnRowCommand //// Defines the Click event. //public event EventHandler<GridCommandEventArgs> RowCommand; ////Invoke delegates registered with the Click event. //protected virtual void OnRowCommand(GridCommandEventArgs e) //{ // if (RowCommand != null) // { // RowCommand(this, e); // } //} private static readonly object _rowCommandHandlerKey = new object(); /// <summary> /// 行内事件 /// </summary> [Category(CategoryName.ACTION)] [Description("行内事件")] public event EventHandler<GridCommandEventArgs> RowCommand { add { Events.AddHandler(_rowCommandHandlerKey, value); } remove { Events.RemoveHandler(_rowCommandHandlerKey, value); } } /// <summary> /// 触发行内事件 /// </summary> /// <param name="e">事件参数</param> protected virtual void OnRowCommand(GridCommandEventArgs e) { EventHandler<GridCommandEventArgs> handler = Events[_rowCommandHandlerKey] as EventHandler<GridCommandEventArgs>; if (handler != null) { handler(this, e); } } #endregion #endregion protected override void Render(HtmlTextWriter writer) { base.Render(writer); if (_columns == null) { return; } writer.Write( String.Format("<table id=\"{0}\" name=\"{1}\" rules=\"all\" border=\"1\" cellspacing=\"0\" style=\"width:100%;border-collapse:collapse;\">", UniqueID, UniqueID)); //RenderHeader(writer); RenderBody(writer); writer.Write("</table>"); } private void RenderBody(HtmlTextWriter writer) { DataTable dt = DataSource as DataTable; if (dt == null || dt.Rows.Count <= 0) { return; } writer.Write("<tbody>"); int rowIndex = 0; int columnIndex = 0; foreach (DataRow row in dt.Rows) { writer.Write(String.Format("<tr {0}>", GetRowStyle())); columnIndex = 0; foreach (GridColumn column in Columns) { if (column is LinkButtonField) { writer.Write(String.Format("<td {0}><a {1} name=\"{2}\">{3}</a></td>", GetItemStyle(column), GetLinkButtonPostBack(column as LinkButtonField, rowIndex, columnIndex), column.UniqueID, row[column.DataField])); } else { writer.Write(String.Format("<td {0}>{1}</td>", GetItemStyle(column), row[column.DataField])); } columnIndex++; } writer.Write("</tr>"); rowIndex++; } writer.Write("</tbody>"); } private String GetLinkButtonPostBack(LinkButtonField linkButton, int rowIndex, int columnIndex) { if (linkButton == null) { return ""; } String arg = String.Format("Command${0}${1}${2}${3}", rowIndex, columnIndex, linkButton.CommandName, linkButton.CommandArgument); String clientScript = Page.ClientScript.GetPostBackClientHyperlink(this, arg); String href = String.Format("href=\"{0}\"", clientScript); return href; } ///其他代码请参照《 Asp.Net服务器控件开发的Grid实现(二)Html标记渲染》 public void RaisePostBackEvent(string eventArgument) { if (eventArgument.StartsWith("Command$")) { string[] commandArgs = eventArgument.Split('$'); if (commandArgs.Length == 5) { GridCommandEventArgs gridCommandEventArgs = new GridCommandEventArgs(Convert.ToInt32(commandArgs[1]), Convert.ToInt32(commandArgs[2]), commandArgs[3], commandArgs[4]); OnRowCommand(gridCommandEventArgs); } } }
注:
1.IPostBackEventHandler接口需要实现RaisePostBackEvent方法。
2.在页面回发时,是通过控件的name来索引到对应的事件,然后回发到目标的。所以对于Grid控件,我们必须要在Render的时候将name赋值,然后在生成回发脚本时将其对应上。
(1)所以在Render函数的table标记的name要赋值,这里使用UniqueID以确保唯一性。
(2)同时在RenderBody时,如果是LinkButtonField的列,就增加回发脚本。即将LinkButtonField渲染到表格的单元格中时,使用a标记渲染,同时将其href赋值相应的脚本。在GetLinkButtonPostBack中生成相应的回发脚本。
(3)GetLinkButtonPostBack函数中,将单元格的列索引和行索引以及LinkButtonField的CommandName和CommandArgument一同作为回发参数。同时,为了便于区分,使用Command作为前缀,并以$作为参数间的分隔符。使用Page.ClientScript.GetPostBackClientHyperlink来生成回发的js脚本,使用该系统方法相应简单,当然也可以直接写出脚本,代码如下。
javascript:__doPostBack('Grid_Edit','Command$0$3$LINK$cmdarg'
4.OnRowCommand事件由三个部分主成。
(1)唯一KEY:使用静态只读的object,即_rowCommandHandlerKey。
(2)将事件添加到委托事件的处理列表中,即RowCommand中。也有直接使用委托来定义的,但性能上不及这种定义。委托直接定义的,原则上是线程安全些。为了能够更好的自定义事件,我们定义了一个事件参数GridCommandEventArgs。代码见后文。
(3)使用Grid的开发者实现的OnRowCommand事件,相当于是按钮的OnClick事件。注意,此事件的命名必须与前面的委托相对应,即只在前面增加一个On。
GridCommandEventArgs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AspNetServerControl { /// <summary> /// 表格行命令事件参数 /// </summary> public class GridCommandEventArgs : EventArgs { private int _rowIndex; /// <summary> /// 行索引 /// </summary> public int RowIndex { get { return _rowIndex; } set { _rowIndex = value; } } private int _columnIndex; /// <summary> /// 列索引 /// </summary> public int ColumnIndex { get { return _columnIndex; } set { _columnIndex = value; } } private string _commandName; /// <summary> /// 命令名称 /// </summary> public string CommandName { get { return _commandName; } set { _commandName = value; } } private string _commandArgument; /// <summary> /// 命令参数 /// </summary> public string CommandArgument { get { return _commandArgument; } set { _commandArgument = value; } } /// <summary> /// 构造函数 /// </summary> /// <param name="rowIndex">行索引</param> /// <param name="columnIndex">列索引</param> /// <param name="commandName">命令名称</param> /// <param name="commandArgument">命令参数</param> public GridCommandEventArgs(int rowIndex, int columnIndex, string commandName, string commandArgument) { _rowIndex = rowIndex; _columnIndex = columnIndex; _commandName = commandName; _commandArgument = commandArgument; } } }
UI代码如下:
<div> <S:Grid runat="server" ID="Grid_Edit" OnRowCommand="Grid_Edit_RowCommand"> <RowStyle Height="50px;" /> <Columns> <S:BoundField runat="server" ID="BoundField1" HeaderText="货号" DataField="NO"> <ItemStyle HorizontalAlign="Center" /> </S:BoundField> <S:BoundField runat="server" ID="BoundField2" HeaderText="类型" DataField="Type"> <ItemStyle HorizontalAlign="Center" /> </S:BoundField> <S:BoundField runat="server" ID="BoundField3" HeaderText="状态" DataField="Status"> <ItemStyle HorizontalAlign="Center" /> </S:BoundField> <S:LinkButtonField runat="server" ID="LinkButtonField1" HeaderText="链接" DataField="Link" CommandName="LINK"> </S:LinkButtonField> </Columns> </S:Grid> </div>
private void InitLoad() { Grid_Edit.DataSource = GenerateData(); } private DataTable GenerateData() { DataTable dt = new DataTable(); dt.Columns.Add("NO"); dt.Columns.Add("Type"); dt.Columns.Add("Status"); dt.Columns.Add("Link"); dt.Rows.Add(new String[] { "H10001", "食品", "已售完", "http://www.baidu.com" }); dt.Rows.Add(new String[] { "H10002", "蔬菜", "待销售", "http://www.baidu.com" }); dt.Rows.Add(new String[] { "H10003", "水果", "待销售", "http://www.baidu.com" }); dt.Rows.Add(new String[] { "H10004", "器具", "销售中", "http://www.baidu.com" }); return dt; } protected void Grid_Edit_RowCommand(object sender, AspNetServerControl.GridCommandEventArgs e) { //需要处理的代码 }这样Grid的回发事件就是实现了。其他的回发处理,可以仿此。
标签:回发事件 ipostbackeventhandle 服务器控件
原文地址:http://blog.csdn.net/xxdddail/article/details/41073415