扩展GridView控件(9) - 给数据行增加右键菜单

来源:互联网 发布:赛诺数据中国手机9月 编辑:程序博客网 时间:2024/05/29 23:23

[源码下载] 

扩展GridView控件(9) - 给数据行增加右键菜单

 

作者:webabcd


/*正式版的实现 开始*/
介绍
扩展GridView控件:
给数据行增加右键菜单,响应服务端事件或超级链接

使用方法(设置ContextMenus集合属性):
Text - 菜单的文本内容
BoundCommandName - 需要绑定的CommandName
NavigateUrl - 链接的URL
Target - 链接的目标窗口或框架
SmartGridView的属性ContextMenuCssClass - 右键菜单的级联样式表 CSS 类名(右键菜单的结构div ul li a)


关键代码
js
/**//*右键菜单 开始*/
yy_sgv_rightMenu = function ()
{
/// <summary>构造函数</summary>

    this._menu = null;
    this._menuItem = null;
    this._handle = null;
    this._target = null;
    this._cssClass = null
};

yy_sgv_rightMenu.prototype =
{
/// <summary>相关属性和相关方法</summary>

    get_menu: function()
    {
        return this._menu;
    },
    set_menu: function(value)
    {
        this._menu = value;
    },
   
    get_handle: function()
    {
        return this._handle;
    },
    set_handle: function(value)
    {
        this._handle = value;
    },
   
    get_target: function()
    {
        return this._target;
    },
    set_target: function(value)
    {
        this._target = value;
    },
   
    get_cssClass: function()
    {
        return this._cssClass;
    },
    set_cssClass: function(value)
    {
        this._cssClass = value;
    },
   
    get_menuItem: function()
    {
        return this._menuItem;
    },
    set_menuItem: function(value)
    {
        this._menuItem = value;
    },


    show:function(e)
    {
        if (this.get_menuItem() == null)
        {
            this.hidden();
            return true;
        }
   
        var rightMenu = this.get_menu();
        if (rightMenu == null)
        {
            rightMenu = document.createElement("div");
        }

        var menuInnerHTML = ""; // 菜单容器里的HTML内容
        var $items = this.get_menuItem();
        var $handle = this.get_handle();
        var $target = this.get_target();
       
        rightMenu.className = "yy_sgv_rightMenuBase";
        if (this.get_cssClass() == null || this.get_cssClass() == "")
            rightMenu.className += " " + "yy_sgv_rightMenu";
        else
            rightMenu.className += " " + this.get_cssClass();           
       
        menuInnerHTML += "<ul>";
       
        for (var i in $items)
        {
            if ($items[i].indexOf("<hr") != -1)
            {
                menuInnerHTML += $items[i];
            }
            else
            {
                if ($target[i] == "")
                {
                    $target[i] = "_self";
                }
           
                menuInnerHTML += "<li><a href=/"" + $handle[i] + "/" target=/"" + $target[i] + "/">";
                menuInnerHTML += $items[i];
                menuInnerHTML += "</a></li>";  
            }
        }
       
        menuInnerHTML += "</ul>";
        // alert(menuInnerHTML);
       
        rightMenu.innerHTML = menuInnerHTML;
       
        rightMenu.style.visibility = "visible";
       
        rightMenu.onmousedown = function(e)
        {
            e=e||window.event;
            document.all ? e.cancelBubble = true : e.stopPropagation();
        }
       
        rightMenu.onselectstart = function()
        {
            return false;
        }
       
        document.body.appendChild(rightMenu);
        this.set_menu(rightMenu); // 方便别的方法引用

        e = e || window.event;
       
        var root = document.documentElement;
        var x = root.scrollLeft + e.clientX;
        var y = root.scrollTop + e.clientY;
       
        if (this.get_menu().clientWidth+e.clientX > root.clientWidth)
        {
            x = x - this.get_menu().clientWidth;
        }
        if (this.get_menu().clientHeight+e.clientY > root.clientHeight)
        {
            y = y - this.get_menu().clientHeight;
        }
       
        this.get_menu().style.left = x + "px";
        this.get_menu().style.top = y + "px";
        this.get_menu().style.visibility = "visible";
       
        this.set_handle(null);
        this.set_menuItem(null);
        this.set_target(null);
       
        return false;
    },

    hidden:function()
    {
        if (this.get_menu() != null)
        {
            this.get_menu().style.visibility = "hidden";
        }
    }
}

if (document.all)
{
    window.attachEvent('onload', yy_sgv_rightMenu = new yy_sgv_rightMenu())
}
else
{
    window.addEventListener('load', yy_sgv_rightMenu = new yy_sgv_rightMenu(), false);
}

function yy_sgv_setRightMenu(handle, menuItem, target, cssClass)
{
/// <summary>设置需要显示的右键菜单</summary>

    yy_sgv_rightMenu.set_handle(handle);
    yy_sgv_rightMenu.set_menuItem(menuItem);
    yy_sgv_rightMenu.set_target(target);
    yy_sgv_rightMenu.set_cssClass(cssClass);
}
/**//*右键菜单 结束*/
css
/**//*右键菜单必须要具有的样式*/
.yy_sgv_rightMenuBase
{}{
    visibility: hidden;
    position: absolute;
}
/**//*右键菜单的示例样式 开始*/
.yy_sgv_rightMenu
{}{
    border-right: 2px outset;
    border-top: 2px outset;
    border-left: 2px outset;
    border-bottom: 2px outset;
    background-color: buttonface;
}
.yy_sgv_rightMenu hr
{}{
    width: 300px;
}
.yy_sgv_rightMenu ul
{}{
    list-style: none; margin:0; padding:0;
}
.yy_sgv_rightMenu ul li
{}{
    vertical-align: bottom;
}
.yy_sgv_rightMenu A {}{ color: MenuText; text-decoration: none; display: block; width: 300px; text-align:center; line-height:20px }
.yy_sgv_rightMenu A:link {}{ color: MenuText; text-decoration: none; }
.yy_sgv_rightMenu A:active {}{ color: MenuText; text-decoration: none; }
.yy_sgv_rightMenu A:visited {}{ color: MenuText; text-decoration: none; }
.yy_sgv_rightMenu A:hover {}{ color: HighlightText; background-color: Highlight; }
/**//*右键菜单的示例样式 结束*/

c#
using System;
using System.Collections.Generic;
using System.Text;

using System.Web.UI.WebControls;
using System.Web.UI;

namespace YYControls.SmartGridViewFunction
{
    /**//// <summary>
    /// 扩展功能:给数据行增加右键菜单
    /// </summary>
    public class ContextMenuFunction : ExtendFunction
    {
        List<string> _rowRightClickButtonUniqueIdList = new List<string>();

        private string _menuItem;
        private string _target;

        /**//// <summary>
        /// 构造函数
        /// </summary>
        public ContextMenuFunction()
            : base()
        {

        }

        /**//// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sgv">SmartGridView对象</param>
        public ContextMenuFunction(SmartGridView sgv)
            : base(sgv)
        {

        }

        /**//// <summary>
        /// 扩展功能的实现
        /// </summary>
        protected override void Execute()
        {
            this._sgv.RowDataBoundDataRow += new SmartGridView.RowDataBoundDataRowHandler(_sgv_RowDataBoundDataRow);
            this._sgv.PreRender += new EventHandler(_sgv_PreRender);
            this._sgv.RenderBegin += new SmartGridView.RenderBeginHandler(_sgv_RenderBegin);

            foreach (ContextMenu cm in this._sgv.ContextMenus)
            {
                string text = cm.Text == null ? "" : cm.Text;
                string target = cm.Target == null ? "" : cm.Target;

                this._menuItem += String.Format(",/"{0}/"", text.Replace(",", ","));
                this._target += String.Format(",/"{0}/"", target.Replace(",", ","));
            }

            this._menuItem = String.Format("new Array({0})", this._menuItem.TrimStart(','));
            this._target = String.Format("new Array({0})", this._target.TrimStart(','));
        }

        void _sgv_RowDataBoundDataRow(object sender, GridViewRowEventArgs e)
        {
            string handle = "";

            // 从用户定义的ContextMenus集合中分解出ContextMenu
            foreach (ContextMenu cm in this._sgv.ContextMenus)
            {
                if (!String.IsNullOrEmpty(cm.NavigateUrl))
                {
                    handle += String.Format(",/"{0}/"", cm.NavigateUrl);
                    continue;
                }
                else if (String.IsNullOrEmpty(cm.BoundCommandName))
                {
                    handle += String.Format(",/"{0}/"", "#");
                    continue;
                }

                foreach (TableCell tc in e.Row.Cells)
                {
                    bool bln = false;

                    foreach (Control c in tc.Controls)
                    {
                        // 如果控件继承自接口IButtonControl
                        if (c is IButtonControl
                            && ((IButtonControl)c).CommandName == cm.BoundCommandName)
                        {
                            handle += String.Format(",/"{0}/"", this._sgv.Page.ClientScript.GetPostBackClientHyperlink(c, ""));
                            _rowRightClickButtonUniqueIdList.Add(c.UniqueID);

                            bln = true;
                            break;
                        }
                    }

                    if (bln)
                    {
                        break;
                    }
                }
            }

            handle = String.Format("new Array({0})", handle.TrimStart(','));

            string oncontextmenuValue =
                String.Format
                (
                    "yy_sgv_setRightMenu({0},{1}_rightMenuItem,{1}_rightMenuTarget, {2})",
                    handle,
                    this._sgv.ClientID,
                    String.IsNullOrEmpty(this._sgv.ContextMenuCssClass) ? "null" : "'" + this._sgv.ContextMenuCssClass + "'"
                );

            // 设置按钮的客户端属性
            YYControls.Helper.Common.SetAttribute(
                e.Row,
                "oncontextmenu",
                oncontextmenuValue,
                AttributeValuePosition.Last);
        }

        /**//// <summary>
        /// SmartGridView的PreRender事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _sgv_PreRender(object sender, EventArgs e)
        {
            // 构造所需脚本
            string scriptString = "";
            scriptString += "document.oncontextmenu=function(evt){return yy_sgv_rightMenu.show(evt);};";
            scriptString += "document.onclick=function(){yy_sgv_rightMenu.hidden();};";

            // 注册所需脚本
            if (!this._sgv.Page.ClientScript.IsClientScriptBlockRegistered("yy_sgv_rightMenu"))
            {
                this._sgv.Page.ClientScript.RegisterClientScriptBlock
                (
                    this._sgv.GetType(),
                    "yy_sgv_rightMenu",
                    scriptString,
                    true
                );
            }

            // 为每个SmartGridView注册与右键菜单相关的变量
            if (!this._sgv.Page.ClientScript.IsClientScriptBlockRegistered(String.Format("yy_sgv_rightMenu_{0}", this._sgv.ClientID)))
            {
                this._sgv.Page.ClientScript.RegisterClientScriptBlock
                (
                    this._sgv.GetType(),
                    String.Format("yy_sgv_rightMenu_{0}", this._sgv.ClientID),
                    String.Format(
                    "var {0}_rightMenuItem={1};var {0}_rightMenuTarget={2};",
                        this._sgv.ClientID,
                        this._menuItem,
                        this._target),
                    true
                );
            }

        }

        /**//// <summary>
        /// RenderBegin
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="writer"></param>
        void _sgv_RenderBegin(object sender, HtmlTextWriter writer)
        {
            foreach (string uniqueId in this._rowRightClickButtonUniqueIdList)
            {
                // 注册回发或回调数据以进行验证
                this._sgv.Page.ClientScript.RegisterForEventValidation(uniqueId);
            }
        }

    }
}

/*正式版的实现 结束*/

/*测试版的实现 开始*/
介绍
给GridView的数据行增加右键菜单可以增加用户体验,不过实现起来挺麻烦的,现在我们扩展一下GridView控件以实现这样的功能。


控件开发
1、新建一个继承自GridView的类。
/**//// <summary>
/// 继承自GridView
/// </summary>
[ToolboxData(@"<{0}:SmartGridView runat='server'></{0}:SmartGridView>")]
public class SmartGridView : GridView
{
}
2、新建一个ContextMenu实体类,有六个属性
using System;
using System.Collections.Generic;
using System.Text;

using System.ComponentModel;
using System.Web.UI;

namespace YYControls.SmartGridView
{
    /**//// <summary>
    /// ContextMenu 的摘要说明。
    /// </summary>
    [ToolboxItem(false)]
    public class ContextMenu
    {
        private string _icon;
        /**//// <summary>
        /// 文字左边的图标的链接
        /// </summary>
        public string Icon
        {
            get { return _icon; }
            set { _icon = value; }
        }

        private string _text;
        /**//// <summary>
        /// 菜单的文字
        /// </summary>
        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }
      
        private string _commandButtonId;
        /**//// <summary>
        /// 所调用的命令按钮的ID
        /// </summary>
        public string CommandButtonId
        {
            get { return _commandButtonId; }
            set { _commandButtonId = value; }
        }

        private string _navigateUrl;
        /**//// <summary>
        /// 链接的url
        /// </summary>
        public string NavigateUrl
        {
            get { return _navigateUrl; }
            set { _navigateUrl = value; }
        }

        private ItemTypeCollection _itemType;
        /**//// <summary>
        /// 右键菜单的项的类别
        /// </summary>
        public ItemTypeCollection ItemType
        {
            get { return _itemType; }
            set { _itemType = value; }
        }

        private TargetCollection _target;
        /**//// <summary>
        /// 链接的target
        /// </summary>
        public TargetCollection Target
        {
            get { return _target; }
            set { _target = value; }
        }


        /**//// <summary>
        /// 右键菜单的项的类别
        /// </summary>
        public enum ItemTypeCollection
        {
            /**//// <summary>
            /// 链接
            /// </summary>
            Link,
            /**//// <summary>
            /// 按钮
            /// </summary>
            Command,
            /**//// <summary>
            /// 分隔线
            /// </summary>
            Separator
        }

        /**//// <summary>
        /// 链接的target
        /// </summary>
        public enum TargetCollection
        {
            /**//// <summary>
            /// 新开窗口
            /// </summary>
            Blank,
            /**//// <summary>
            /// 当前窗口
            /// </summary>
            Self,
            /**//// <summary>
            /// 跳出框架
            /// </summary>
            Top
        }
    }
}

3、新建一个继承自CollectionBase的类ContextMenus
using System.Collections;
using System.ComponentModel;
using System.Web.UI;

namespace YYControls.SmartGridView
{
    /**//// <summary>
    /// ContextMenus 的摘要说明。
    /// 注意要继承自CollectionBase
    /// </summary>
    [
    ToolboxItem(false),
    ParseChildren(true)
    ]
    public class ContextMenus : CollectionBase
    {
        /**//// <summary>
        /// 构造函数
        /// </summary>
        public ContextMenus()
            : base()
        {
        }

        /**//// <summary>
        /// 实现IList接口
        /// 获取或设置指定索引处的元素。
        /// </summary>
        /// <param name="index">要获得或设置的元素从零开始的索引</param>
        /// <returns></returns>
        public ContextMenu this[int index]
        {
            get
            {
                return (ContextMenu)base.List[index];
            }
            set
            {
                base.List[index] = (ContextMenu)value;
            }
        }

        /**//// <summary>
        /// 实现IList接口
        /// 将某项添加到 System.Collections.IList 中。
        /// </summary>
        /// <param name="item">要添加到 System.Collections.IList 的 System.Object。</param>
        public void Add(ContextMenu item)
        {
            base.List.Add(item);
        }

        /**//// <summary>
        /// 实现IList接口
        /// 从 System.Collections.IList 中移除特定对象的第一个匹配项。
        /// </summary>
        /// <param name="index">要从 System.Collections.IList 移除的 System.Object</param>
        public void Remove(int index)
        {
            if (index > -1 && index < base.Count)
            {
                base.List.RemoveAt(index);
            }
        }

        /**//// <summary>
        /// ToString()
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return "ContextMenus";
        }
    }
}

4、在继承自GridView的类中加一个复杂对象属性,该复杂对象就是第3步创建的那个ContextMenus
        private ContextMenus _contextMenus;
        /**//// <summary>
        /// 行的右键菜单集合
        /// </summary>
        [
        PersistenceMode(PersistenceMode.InnerProperty),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        Description("行的右键菜单"),
        Category("扩展")
        ]
        public virtual ContextMenus ContextMenus
        {
            get
            {
                if (_contextMenus == null)
                {
                    _contextMenus = new ContextMenus();
                }
                return _contextMenus;
            }
        }
5、新建一个JavaScriptConstant类,把我们要用到的javascript存在一个常量里
using System;
using System.Collections.Generic;
using System.Text;

namespace YYControls.SmartGridView
{
    /**//// <summary>
    /// javascript
    /// </summary>
    public class JavaScriptConstant
    {
        internal const string jsContextMenu = @"<script type=""text/javascript"">
        //<![CDATA[
        // 数据行的ClientId
        var _rowClientId = '';

        // 以下实现右键菜单,网上找的,不知道原创是谁
        function contextMenu()
        {
            this.items = new Array();
            this.addItem = function (item)
            {
                this.items[this.items.length] = item;
            }

            this.show = function (oDoc)
            {
                var strShow = '';
                var i;

                // 加上word-break: keep-all; 防止菜单项换行
                strShow = ""<div id='rightmenu' style='word-break: keep-all;BACKGROUND-COLOR: #ffffff; BORDER: #000000 1px solid; LEFT: 0px; POSITION: absolute; TOP: 0px; VISIBILITY: hidden; Z-INDEX: 10'>"";
                strShow += ""<table border='0' height='"";
                strShow += this.items.length * 20;
                strShow += ""' cellpadding='0' cellspacing='0'>"";
                strShow += ""<tr height='3'><td bgcolor='#d0d0ce' width='2'></td><td>"";
                strShow += ""<table border='0' width='100%' height='100%' cellpadding=0 cellspacing=0 bgcolor='#ffffff'>"";
                strShow += ""<tr><td bgcolor='#d0d0ce' width='23'></td><td><img src=' ' height='1' border='0'></td></tr></table>"";
                strShow += ""</td><td width='2'></td></tr>"";
                strShow += ""<tr><td bgcolor='#d0d0ce'></td><td>"";
                strShow += ""<table border='0' width='100%' height='100%' cellpadding=3 cellspacing=0 bgcolor='#ffffff'>"";
               
                oDoc.write(strShow);

                for(i=0; i<this.items.length; i++)
                {
                    this.items[i].show(oDoc);
                }
               
                strShow = ""</table></td><td></td></tr>"";
                strShow += ""<tr height='3'><td bgcolor='#d0d0ce'></td><td>"";
                strShow += ""<table border='0' width='100%' height='100%' cellpadding=0 cellspacing=0 bgcolor='#ffffff'>"";
                strShow += ""<tr><td bgcolor='#d0d0ce' width='23'></td><td><img src=' ' height='1' border='0'></td></tr></table>"";
                strShow += ""</td><td></td></tr>"";
                strShow += ""</table></div>/n"";
               
                oDoc.write(strShow);
            }
        }

        function contextItem(text, icon, cmd, url, target, type)
        {
            this.text = text ? text : '';
            this.icon = icon ? icon : '';
            this.cmd = cmd ? cmd : '';
            this.url = url ? url : '';
            this.target =target ? target : '';
            this.type = type ? type : 'Link';


            this.show = function (oDoc)
            {
                var strShow = '';

                if(this.type == 'Link' || this.type == 'Command')
                {
                    strShow += ""<tr "";
                    strShow += ""onmouseover=/""changeStyle(this, 'on');/"" "";
                    strShow += ""onmouseout=/""changeStyle(this, 'out');/"" "";

                    if (this.type == 'Command')
                    {
                        // 右键菜单是按钮类型,调用所对应的按钮的click事件
                        strShow += ""onclick=/""document.getElementById("";
                        strShow += ""_rowClientId + "";
                        strShow += ""'_"";
                        strShow += this.cmd;
                        strShow += ""').click()"";
                    }
                    else
                    {
                        // 右键菜单是链接类型
                        if (this.target == 'Top') this.target = 'top';
                        if (this.target == 'Self') this.target = 'self';

                        if (this.target == 'top' || this.target == 'self')
                        {
                            strShow += ""onclick=/"""";
                            strShow += this.target;
                            strShow += "".location='"";
                            strShow += this.url;
                            strShow += ""'"";
                        }
                        else
                        {
                            strShow += ""onclick=/""window.open('"";
                            strShow += this.url;
                            strShow += ""')"";
                        }
                    }  
                    strShow += ""/"">"";
                    strShow += ""<td class='ltdexit' width='16'>"";

                    if (this.icon == '')
                    {
                        strShow += '&nbsp;';
                    }
                    else
                    {
                        strShow += ""<img border='0' src='"";
                        strShow += this.icon;
                        strShow += ""' width='16' height='16' style='POSITION: relative'></img>"";
                    }

                    strShow += ""</td><td class='mtdexit'>"";
                    strShow += this.text;
                    strShow += ""</td><td class='rtdexit' width='5'>&nbsp;</td></tr>"";
                }
                // 右键菜单是分隔线
                else if (this.type == 'Separator')
                {
                    strShow += ""<tr><td class='ltdexit'>&nbsp;</td>"";
                    strShow += ""<td class='mtdexit' colspan='2'><hr color='#000000' size='1'></td></tr>"";
                }

                oDoc.write(strShow);
            }
        }

        function changeStyle(obj, cmd)
        {
            if(obj)
            {
                try
                {
                    var imgObj = obj.children(0).children(0);

                    if(cmd == 'on')
                    {
                        obj.children(0).className = 'ltdfocus';
                        obj.children(1).className = 'mtdfocus';
                        obj.children(2).className = 'rtdfocus';
                       
                        if(imgObj)
                        {
                            if(imgObj.tagName.toUpperCase() == 'IMG')
                            {
                                imgObj.style.left = '-1px';
                                imgObj.style.top = '-1px';
                            }
                        }
                    }
                    else if(cmd == 'out')
                    {
                        obj.children(0).className = 'ltdexit';
                        obj.children(1).className = 'mtdexit';
                        obj.children(2).className = 'rtdexit';

                        if(imgObj)
                        {
                            if(imgObj.tagName.toUpperCase() == 'IMG')
                            {
                                imgObj.style.left = '0px';
                                imgObj.style.top = '0px';
                            }
                        }
                    }
                }
                catch (e) {}
            }
        }

        function showMenu(rowClientId)
        {
            _rowClientId = rowClientId;

            var x, y, w, h, ox, oy;

            x = event.clientX;
            y = event.clientY;

            var obj = document.getElementById('rightmenu');

            if (obj == null)
                return true;

            ox = document.body.clientWidth;
            oy = document.body.clientHeight;

            if(x > ox || y > oy)
                return false;

            w = obj.offsetWidth;
            h = obj.offsetHeight;

            if((x + w) > ox)
                x = x - w;

            if((y + h) > oy)
                y = y - h;

        
            // obj.style.posLeft = x + document.body.scrollLeft;
            // obj.style.posTop = y + document.body.scrollTop;
            // xhtml不支持上面的了
            // 就是说如果你的页头声明了页是xhtml的话就不能用上面那句了,vs2005创建的aspx会默认加上xhtml声明
            // 此时应该用如下的方法
            obj.style.posLeft = x + document.documentElement.scrollLeft;
            obj.style.posTop = y + document.documentElement.scrollTop;

            obj.style.visibility = 'visible';

            return false;
        }

        function hideMenu()
        {
            if(event.button == 0)
            {
                var obj = document.getElementById('rightmenu');
                if (obj == null)
                    return true;

                obj.style.visibility = 'hidden';
                obj.style.posLeft = 0;
                obj.style.posTop = 0;
            }
        }

        function writeStyle()
        {
            var strStyle = '';

            strStyle += ""<STYLE type='text/css'>"";
            strStyle += ""TABLE {Font-FAMILY: 'Tahoma','Verdana','宋体'; FONT-SIZE: 9pt}"";
            strStyle += "".mtdfocus {BACKGROUND-COLOR: #ccccff; BORDER-BOTTOM: #000000 1px solid; BORDER-TOP: #000000 1px solid; CURSOR: hand}"";
            strStyle += "".mtdexit {BACKGROUND-COLOR: #ffffff; BORDER-BOTTOM: #ffffff 1px solid; BORDER-TOP: #ffffff 1px solid}"";
            strStyle += "".ltdfocus {BACKGROUND-COLOR: #ccccff; BORDER-BOTTOM: #000000 1px solid; BORDER-TOP: #000000 1px solid; BORDER-LEFT: #000000 1px solid; CURSOR: hand}"";
            strStyle += "".ltdexit {BACKGROUND-COLOR: #d0d0ce; BORDER-BOTTOM: #d0d0ce 1px solid; BORDER-TOP: #d0d0ce 1px solid; BORDER-LEFT: #d0d0ce 1px solid}"";
            strStyle += "".rtdfocus {BACKGROUND-COLOR: #ccccff; BORDER-BOTTOM: #000000 1px solid; BORDER-TOP: #000000 1px solid; BORDER-RIGHT: #000000 1px solid; CURSOR: hand}"";
            strStyle += "".rtdexit {BACKGROUND-COLOR: #ffffff; BORDER-BOTTOM: #ffffff 1px solid; BORDER-TOP: #ffffff 1px solid; BORDER-RIGHT: #ffffff 1px solid}"";
            strStyle += ""</STYLE>"";

            document.write(strStyle);
        }

        function makeMenu()
        {
            var myMenu, item;

            myMenu = new contextMenu();

            // 增加右键菜单项 开始
            // item = new contextItem("", "", "", "", "", "");
            // 1-菜单项的文本
            // 2-图标链接
            // 3-所调用的命令按钮的ID
            // 4-链接地址
            // 5-链接的target
            // 6-右键菜单的项的类别
            // myMenu.addItem(item);

            [$MakeMenu$]
            // 增加右键菜单项 结束

            myMenu.show(this.document);

            delete item;

            delete myMenu;
        }

        function toggleMenu(isEnable)
        {
            if(isEnable)
                document.oncontextmenu = showMenu;
            else
                document.oncontextmenu = new function() {return true;};
        }

        writeStyle();

        makeMenu();

        document.onclick = hideMenu;
        //]]>
        </script>";
    }
}

6、重写OnPreRender方法,注册上面那段客户端脚本
        /**//// <summary>
        /// OnPreRender
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            if (ContextMenus.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                foreach (ContextMenu cm in ContextMenus)
                {
                    // item = new contextItem("", "", "", "", "", "");
                    // 1-菜单项的文本
                    // 2-图标链接
                    // 3-所调用的命令按钮的ID
                    // 4-链接地址
                    // 5-链接的target
                    // 6-右键菜单的项的类别

                    // 命令按钮
                    if (cm.ItemType == ContextMenu.ItemTypeCollection.Command)
                    {
                        sb.Append("item = new contextItem(/"" + cm.Text +
                            "/", /"" + ResolveUrl(cm.Icon) + "/", /"" +
                            cm.CommandButtonId + "/", /"/", /"/", /"Command/");");
                    }
                    // 链接
                    else if (cm.ItemType == ContextMenu.ItemTypeCollection.Link)
                    {
                        sb.Append("item = new contextItem(/"" + cm.Text +
                            "/", /"" + ResolveUrl(cm.Icon) + "/", /"/", /"" +
                            cm.NavigateUrl + "/", /"" +
                            cm.Target + "/", /"Link/");");
                    }
                    // 分隔线
                    else if (cm.ItemType == ContextMenu.ItemTypeCollection.Separator)
                    {
                        sb.Append("item = new contextItem(/"/", /"/", /"/", /"/", /"/", /"Separator/");");
                    }

                    sb.Append("myMenu.addItem(item);");
                }

                // 注册客户端代码
                if (!Page.ClientScript.IsClientScriptBlockRegistered("jsContextMenu"))
                {
                    Page.ClientScript.RegisterClientScriptBlock(
                        this.GetType(),
                        "jsContextMenu", JavaScriptConstant.jsContextMenu.Replace("[$MakeMenu$]", sb.ToString())
                        );
                }
            }

            base.OnPreRender(e);
        }

7、重写OnRowDataBound给数据行增加客户端代码以调用我们注册的那段javascript,从而实现给GridView的数据行增加右键菜单的功能。
        /**//// <summary>
        /// OnRowDataBound
        /// </summary>
        /// <param name="e"></param>
        protected override void OnRowDataBound(GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                if (ContextMenus.Count > 0)
                {
                    // 给数据行增加客户端代码
                    e.Row.Attributes.Add("oncontextmenu", "showMenu('" + e.Row.ClientID + "');return false;");
                }
            }

            base.OnRowDataBound(e);
        }


控件使用
添加这个控件到工具箱里,然后拖拽到webform上,设置如下属性:ItemType为右键菜单的项的类别(Link,Command,Separator);Icon为文字左边的图标的链接;Text为菜单的文字;CommandButtonId为所调用的命令按钮的ID;NavigateUrl为链接的url;Target为链接的target(Blank,Self,Top)
ObjData.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.ComponentModel;

/**//// <summary>
/// OjbData 的摘要说明
/// </summary>
public class OjbData
{
    public OjbData()
    {
        //
        // TODO: 在此处添加构造函数逻辑
        //
    }

    [DataObjectMethod(DataObjectMethodType.Select, true)]
    public DataTable Select()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("no", typeof(string));
        dt.Columns.Add("name", typeof(string));

        for (int i = 0; i < 30; i++)
        {
            DataRow dr = dt.NewRow();
            dr[0] = "no" + i.ToString().PadLeft(2, '0');
            dr[1] = "name" + i.ToString().PadLeft(2, '0');

            dt.Rows.Add(dr);
        }

        return dt;
    }
}

Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!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 runat="server">
    <title>SmartGridView测试</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <yyc:SmartGridView ID="SmartGridView1" runat="server" DataSourceID="ObjectDataSource1"
                AutoGenerateColumns="false">
                <Columns>
                    <asp:BoundField DataField="no" HeaderText="序号" SortExpression="no" ItemStyle-Width="100px" />
                    <asp:BoundField DataField="name" HeaderText="名称" SortExpression="name" ItemStyle-Width="100px" />
                    <asp:BoundField DataField="no" HeaderText="序号" SortExpression="no" ItemStyle-Width="100px" />
                    <asp:BoundField DataField="name" HeaderText="名称" SortExpression="name" ItemStyle-Width="100px" />
                    <asp:BoundField DataField="no" HeaderText="序号" SortExpression="no" ItemStyle-Width="100px" />
                    <asp:BoundField DataField="name" HeaderText="名称" SortExpression="name" ItemStyle-Width="100px" />
                    <asp:TemplateField>
                        <footerstyle cssclass="hidden" />
                        <headerstyle cssclass="hidden" />
                        <itemstyle cssclass="hidden" />
                        <itemtemplate>
                    <asp:Button id="btnRightMenuButton" runat="server" CommandName="RightMenuButton" CommandArgument='<%# Container.DataItemIndex %>' />
                </itemtemplate>
                    </asp:TemplateField>
                </Columns>
                <ContextMenus>
                    <yyc:ContextMenu ItemType="Command" Text="右键菜单按钮测试" Icon="~/Images/button.gif" CommandButtonId="btnRightMenuButton" />
                    <yyc:ContextMenu ItemType="Separator" />
                    <yyc:ContextMenu ItemType="Link" Text="控件源代码" Icon="~/Images/button.gif" NavigateUrl="http://webabcd.cnblogs.com"
                        Target="Blank" />
                </ContextMenus>
            </yyc:SmartGridView>
            <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="Select"
                TypeName="OjbData"></asp:ObjectDataSource>
        </div>
    </form>
</body>
</html>

注:如果想修改右键菜单的样式,请自行修改javascript,我就不把他们弄出来了。

/*测试版的实现 结束*/ 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 网购手机受骗后电话打不通怎么办 淘宝买的东西发错了怎么办 淘宝上买的东西发错了怎么办 淘宝上买的东西发多了怎么办 淘宝上买的东西出现问题怎么办 淘宝买东西未收到货显示签收怎么办 网上一张车票两人同时付款了怎么办 微信付款时显示银行卡被锁定怎么办 微信忘记支付密码怎么办没有银行卡 支付宝赏金扫码支付不行怎么办 网购收货时发现货物已破损怎么办 货物丢失了不承认调查出来了怎么办 小米商城已签收未收到了怎么办 网购的一只荷兰猪现在怎么办 中通快递的掌中通好评怎么办 唯品会快递被签收却没收到货怎么办 拼多多快递签收了但没收到货怎么办 顺丰代收签收成功要强制退款怎么办 淘宝付了钱如果商家没货了怎么办 别人拿走我的货不给钱怎么办 快递出途中损坏签单后才发现怎么办 顾客支付宝少付了钱人走了怎么办 顾客通过收钱码付的钱少了怎么办 寄顺丰快递收件人号码填错了怎么办 京东退货售后说是有划痕怎么办 手机上快递员软件签收错了怎么办 苹果手机进网许可证丢了怎么办 作废的普票发票联丢失怎么办 想退换货但是发票丢了怎么办 快递没有当面验货造成的丢件怎么办 退货卖家收货验货说有问题怎么办 没当着快递人员面验货少货怎么办 微信绑定的银行了被快捷支付怎么办 银行支付到微信支付里的钱怎么办 微信绑定银行忘支付密码忘了怎么办 微信桂林银行不可以支付怎么办 微信忘记支付密码和银行卡号怎么办 京东商城迟迟不通过退货审核怎么办 网上购物想退款商家要我拒收怎么办 运输公司对车主不买保险怎么办 苹果平板限制访问密码忘了怎么办