码迷,mamicode.com
首页 > Web开发 > 详细

Asp.Net服务器控件开发的Grid实现(四)回发事件

时间:2014-11-13 11:00:00      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:回发事件   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'

3.在RaisePostBackEvent收到回发事件后,将相应的参数分离出来,并作相应的处理。为了参够让使用Grid自定义回发后调用的事件,我们自定义了一个OnRowCommand事件。

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的回发事件就是实现了。其他的回发处理,可以仿此。




Asp.Net服务器控件开发的Grid实现(四)回发事件

标签:回发事件   ipostbackeventhandle   服务器控件   

原文地址:http://blog.csdn.net/xxdddail/article/details/41073415

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!