webabcd - 专注于asp.net, html5, silverlight

ASP.NET
从现在开始 一切都不晚
posts - 287, comments - 7866, trackbacks - 594, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理
GridView既强大又好用。为了让它更强大、更好用,我们来写一个继承自GridView的控件。
[索引页]
[源码下载]


扩展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,我就不把他们弄出来了。

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


OK
[源码下载] 

Feedback

#1楼  回复 引用 查看   

2007-02-01 22:33 by 志扬      
越来越牛

#2楼[楼主]  回复 引用 查看   

2007-02-01 22:44 by webabcd      
@志扬
:)
核心javascript代码是从网上找的

#3楼  回复 引用 查看   

2007-02-02 09:43 by CooS      
接下来还有什么功能?

#4楼[楼主]  回复 引用 查看   

2007-02-02 11:25 by webabcd      
@CooS
我这个礼拜把分页重写完了就完了

#5楼  回复 引用   

2007-02-02 15:15 by ivw[未注册用户]
呵呵,现在又能上了,今天早上上不了

#6楼[楼主]  回复 引用 查看   

2007-02-02 17:42 by webabcd      
@ivw
是啊,我早上也上不了

#7楼  回复 引用   

2007-02-03 15:17 by ivw[未注册用户]
在gridview里建了一个checkbox的模板列,但不知道什么原因,例如一共有3页,现在是第1页,我在外面建一个按钮,内容是pageindex=1;一按它后能显示第1页的内容,但checkbox模板列,item项里的checkbox全不见了。如果转到其它页就没事,但如果转到当前页就会出现这个问题了。

#8楼  回复 引用   

2007-02-03 16:36 by ivw[未注册用户]
找到问题所在了,正试解决,是我自己动态创建列时出现的问题

#9楼  回复 引用   

2007-02-03 17:01 by ivw[未注册用户]
请问你知道为什么使用动态创建列时会出现上面的问题吗?

#10楼[楼主]  回复 引用 查看   

2007-02-03 18:49 by webabcd      
@ivw
你是怎么动态创建列的?
跟踪一下,应该是显示GridView的时候没用调用你创建列的那个方法

#11楼  回复 引用   

2007-02-03 19:14 by ivw[未注册用户]
创建列应该没问题。如果不加!IsPostBack他会重新写一个列,但会保留原来的,加了!IsPostBack就会出现上面的情况,应该在重写时不能保存动态创建的列,我在网上也找了下,发现有人发过这样的贴,但没说解决办法。你自己可以测试一下,动态创建一个模板列,item里添加一个checkbox,放一个按钮,不用写代码,直接按一下就会出现情况了。

#12楼[楼主]  回复 引用 查看   

2007-02-03 20:03 by webabcd      
@ivw
我试了,没问题
我用的动态创建列的方法是这样的
http://www.cnblogs.com/webabcd/archive/2006/12/21/598819.html

#13楼  回复 引用   

2007-02-05 09:17 by ivw[未注册用户]
你是用LoadTemplate()方法还是用MyTemplate的类啊

#14楼[楼主]  回复 引用 查看   

2007-02-05 09:30 by webabcd      
@ivw
用的是自定义模板类

#15楼  回复 引用   

2007-02-05 10:02 by ivw[未注册用户]
郁闷啊,我试了两个方法都没成功,还是在回发后item项里的checkbox不见了。

#16楼  回复 引用   

2007-02-05 10:06 by ivw[未注册用户]
我用的方法。如果不加!Page.IsPostBack就会每次刷新出现新的一列。

public class MyTemplate : ITemplate
{

/// <summary>
/// 构造函数
/// </summary>
public MyTemplate()
{

}

/// <summary>
/// 实现接口ITemplate的方法

public void InstantiateIn(Control container)
{
CheckBox l = new CheckBox();
l.ID = "chkdel";
container.Controls.Add(l);
}
}

在页面的page_load里调用

if (SmartGridView1.CreateBox)
{
TemplateField customField = new TemplateField();

customField.HeaderStyle.Width = 15;
customField.ItemStyle.Width = 15;
customField.HeaderStyle.VerticalAlign = VerticalAlign.Bottom;
customField.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
customField.ItemTemplate = new MyTemplate();
SmartGridView1.Columns.Add(customField);

}

#17楼[楼主]  回复 引用 查看   

2007-02-05 12:20 by webabcd      
@ivw
不晓得了,我这里确实没问题

#18楼  回复 引用   

2007-02-05 14:34 by ivw[未注册用户]
你发个测试的给我试试好吗?我也不知道是什么原因。我把创建模板列的放到Render里就没这个问题。但另外一问题就是只要执行Columns.Add(customField); 这句后就会读多一次SQL数据库,这个我是用跟踪里看到的。不知你有试过没有。

#19楼[楼主]  回复 引用 查看   

2007-02-05 15:01 by webabcd      
@ivw
公司防火墙不让传啊
回家后发给你

#20楼  回复 引用   

2007-02-05 15:17 by ivw[未注册用户]
你试试在你的控件里加多个功能,选择是否自动添加checkbox列。看会不会出现这个问题。 

#21楼[楼主]  回复 引用 查看   

2007-02-05 15:34 by webabcd      
@ivw
我觉得你可以这样做

!Page.IsPostBack
里你动态增加列了 比如GridView.Columns.Add(col);

然后回发后不执行这句了,所以没有任何数据,所以回发后可以先
GridView.Columns.Clear();

GridView.Columns.Add(col);

#22楼  回复 引用   

2007-02-05 15:51 by ivw[未注册用户]
这个我之前想过,那也有一种可能性就是说我另外用手动方式加了一个模板列,它会不会也clear了呢?

#23楼[楼主]  回复 引用 查看   

2007-02-05 16:08 by webabcd      
@ivw
你也可以禁用GridView的ViewState
然后不用IsPostBack判断了
也就是每次加载页面都动态添加列就ok了

#24楼  回复 引用   

2007-02-05 16:11 by ivw[未注册用户]
如果禁用了,可能以后扩展会带来不便啊。

有试过这个吗?
“我把创建模板列的放到Render里就没这个问题。但另外一问题就是只要执行Columns.Add(customField); 这句后就会读多一次SQL数据库,这个我是用跟踪里看到的。不知你有试过没有。”

#25楼[楼主]  回复 引用 查看   

2007-02-05 16:24 by webabcd      
@ivw
没办法啊
如果动态创建列的话,禁用ViewState就不会出现你的问题了

把创建列放到Render总觉得不太合适啊

我跟了一下,只读一次数据库

#26楼  回复 引用   

2007-02-05 16:27 by ivw[未注册用户]
不会吧。怎么我这里会出现两次呢?你是不是在render里加上去啊?

#27楼[楼主]  回复 引用 查看   

2007-02-05 22:36 by webabcd      
@ivw
我没在Render里加

我觉得放在Render里没问题是因为每次绑定都会执行Render,所以不会有问题。

执行两次估计是Render之前GridView被绑定了读一次库,Render里你动态添加列又读一次库

#28楼  回复 引用   

2007-02-08 10:18 by Bruse[未注册用户]
当我不使用分页的方式,而是让页面往下滚动,当我往下滚动页面的时候,在使用右键菜单的时候,发现右键菜单不是随着鼠标出现,还是在最上面的某个地方,一开始还以为右键菜单没有出现呢,请问这个脚本错误在什么地方修改,怎么修改,谢谢!

#29楼[楼主]  回复 引用 查看   

2007-02-08 11:29 by webabcd      
@Bruse
我试了一下,没问题啊

#30楼  回复 引用   

2007-02-08 16:37 by Bruse[未注册用户]
当我把下面的这段话去掉以后,也就是把锁定表头的功能去掉以后,页面的显示将超出一页,而当我滚动滚动条到下面以后,Context Menu就不再跟随鼠标了,而是会随着鼠标有一个偏移,你试一下。
<FixRowCol FixColumnIndices="0,1" FixRowIndices="0" IsFixHeader="True" IsFixPager="true" TableHeight="400px" TableWidth="600px" />

#31楼[楼主]  回复 引用 查看   

2007-02-08 18:05 by webabcd      
@Bruse
发现了,严重的bug啊,等我回家看看,解决后再贴出来
谢谢兄弟

#32楼[楼主]  回复 引用 查看   

2007-02-08 21:49 by webabcd      
@Bruse
找到原因了
原来的
document.body.scrollLeft;
document.body.scrollTop;
在xhtml中无法取到正确的值

改成下面这句就ok了
document.documentElement.scrollLeft;
document.documentElement.scrollTop;

已经把改好的上传了,你可以自己改,也可以重新下载

再次谢谢兄弟发现bug

#33楼  回复 引用   

2007-02-09 10:29 by Bruse[未注册用户]
谢谢兄弟的及时支持,你的这个扩展的控件也给了我很多的启示,同样谢谢你,希望我们以后能经常交流

#34楼[楼主]  回复 引用 查看   

2007-02-09 12:14 by webabcd      
@Bruse
:)
嗯,大家多交流才会提高的快

#35楼  回复 引用   

2007-02-09 19:29 by Bruse[未注册用户]
还有一个问题,就是当右键菜单比较多,菜单体本身比较长的时候,由于程序没有计算菜单和浏览器边界之间的距离,所以菜单可能会超出浏览器的边界,导致部分右键菜单的菜单项无法被点到,是不是应该根据浏览器和右键菜单的相对位置重新计算右键菜单应该出现在鼠标的相对位置,麻烦兄弟在修改一下,谢谢!

#36楼[楼主]  回复 引用 查看   

2007-02-09 22:02 by webabcd      
@Bruse
在div的样式里加上这句“word-break: keep-all;”就ok了

改好了,请重新下载

#37楼  回复 引用   

2007-02-15 16:50 by simhare[未注册用户]
控件使用
添加这个控件到工具箱里,然后拖拽到webform上

请教:这个控件是如何生成的 csc /t:library contextMenu.cs
2.csc /t:library /r:contextMenu.dll contextMenus.cs
3.csc /t:library JavascriptConstant.cs
4.csc /t:library /r:contextMenus.dll /r:JavascriptConstant.dll smartGridView.cs 这里就不行了,前三步都没问题

错误:::::::::::::::::::::::::::::
:javascriptConstant.dll is a binary File not a text FsmartGridView.cs(18,13): error CS0246: The type or namespace name 'ContextMenus
could not be found (are you missing a using directive or an assembly
reference?)
smartGridView.cs(29,20): error CS0246: The type or namespace name 'ContextMenus
could not be found (are you missing a using directive or an assembly
reference?)
smartGridView.cs(25,5): error CS0246: The type or namespace name
'DesignerSerializationVisibility' could not be found (are you missing a
using directive or an assembly reference?)
smartGridView.cs(26,5): error CS0246: The type or namespace name 'Description'
could not be found (are you missing a using directive or an assembly
reference?)
smartGridView.cs(27,5): error CS0246: The type or namespace name 'Category'
could not be found (are you missing a using directive or an assembly
reference?)ile

#38楼  回复 引用   

2007-02-15 16:57 by simhare[未注册用户]
应该是编译生成的.dll文件,在toolBox里右键-〉choose Item->定位到该.dll文件,来添加该控件?

#39楼[楼主]  回复 引用 查看   

2007-02-15 17:15 by webabcd      
@simhare
我就是在VS里release的,然后release文件夹里就会有一个dll啊

源代码中是在debug文件夹里有一个dll

#40楼  回复 引用   

2007-02-15 17:23 by simhare[未注册用户]
哦,我错了,我下载到了你提供的打包的文件,感谢!

#41楼[楼主]  回复 引用 查看   

2007-02-15 17:25 by webabcd      
@simhare
:)

#42楼  回复 引用   

2007-04-04 14:29 by Bruse[未注册用户]
请问一下如何在右键菜单里发起一个纯粹的客户端脚本事件而不要进行Server端的回调

#43楼[楼主]  回复 引用 查看   

2007-04-04 16:35 by webabcd      
@Bruse
现在的版本不行,最近很忙,等腾出时间来我就把这个功能加上
有新的版本我会在http://www.cnblogs.com/webabcd/archive/2007/02/04/639830.html这里补上评论的
争取一个礼拜内能抽时间改完

#44楼  回复 引用   

2007-04-24 17:25 by 软奇[未注册用户]
DLL文件启动后占用CPU很大,我用VB.NET引用,全部复制代码都不能实现其功能,怎么回事,的却功能很实用.

#45楼[楼主]  回复 引用 查看   

2007-04-24 17:59 by webabcd      
@软奇
占cpu是因为启用了固定行、列的功能(在CSS中用Expression会使运行速度变得非常的慢)

直接引用dll就ok了

#46楼  回复 引用   

2007-06-11 15:03 by cc[未注册用户]
扩展GridView控件(九)——给数据行增加右键菜单

------

如果一个页面用二个以上的girdview,你这种方式就没用了咯,只能是第一个gridview有用,

如果能实现在一个页面上的多个gridview都可以增加不同的右键菜单就好了

#47楼[楼主]  回复 引用 查看   

2007-06-11 15:58 by webabcd      
@cc
确实有这问题,之前一直忙,最近好一些了,正准备修改这个东东

#48楼  回复 引用   

2007-07-31 12:01 by Fengdesudu[未注册用户]
不错

#49楼[楼主]  回复 引用 查看   

2007-07-31 13:16 by webabcd      
@Fengdesudu
:)
谢谢

#50楼  回复 引用   

2007-08-30 09:22 by zidingxiang[未注册用户]
感觉这个代码非常的好!
请问下载源代码后,该如能运行啊!
扩展的控件如何加载啊

#51楼[楼主]  回复 引用 查看   

2007-08-30 10:21 by webabcd      
@zidingxiang
:)
下载后运行一下就行了
附带有demo

以后用的时候把编译好的dll添加到工具箱就好了

#52楼  回复 引用   

2007-11-30 11:28 by 为平[未注册用户]
你好 我把你的控件加入到我自己的站点中在第一次执行右键菜单时成功运行,但是第二次执行右键菜单时出现回调错误
是需要其他什么设置么?谢谢
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

#53楼  回复 引用   

2007-11-30 11:33 by 为平[未注册用户]
我发现在页面上注册
EnableEventValidation="false"

就可以正常运行
但是这应该不是解决办法
谢谢

#54楼[楼主]  回复 引用 查看   

2007-11-30 21:55 by webabcd      
@为平
请查看一下我随源代码提供的demo
是可以不用设置EnableEventValidation="false"的

#55楼  回复 引用   

2007-12-06 10:20 by 为平[未注册用户]
那一般什么情况下会出现这个问题啊?
因为好像我把你的控件拖到我的网站里面来还是有这个问题
谢谢

#56楼  回复 引用   

2007-12-06 10:33 by 为平[未注册用户]
恩 我发现
我如果每次都在PageLoad里面Bind一下数据的话不会出这个错。
但如果我把Bind数据放在ISPostBack后面,也就是说如果是按钮导致的Postback我就不绑定了
这样就会出现这个错误

#57楼  回复 引用   

2007-12-06 11:37 by 为平[未注册用户]
我里面代码跟踪进去看了一下是数据绑定以后m_RowRightClickButtonUniqueIdList 这个里面有值 所以
foreach (string uniqueId in this.m_RowRightClickButtonUniqueIdList)
{
this.Page.ClientScript.RegisterForEventValidation(uniqueId);
}
这个注册都成功了

但是一旦当我执行了一次Command之后
m_RowRightClickButtonUniqueIdList 这个里面的值没有了
所以后面的注册全都没有执行
因此导致错误

这个是哪里出问题了呢?
谢谢

#58楼  回复 引用   

2007-12-06 11:47 by 为平[未注册用户]
哦 我知道了,我操作之后没有绑定数据,所以会这样
应该是只要在操作了之后绑定数据可能就不会出错了
谢谢

#59楼[楼主]  回复 引用 查看   

2007-12-06 13:31 by webabcd      
@为平
:)
这个问题也一直困扰我
我的解决办法和你一样,每次回发后都绑定,而且这样做也可以禁掉viewstate

#60楼  回复 引用   

2008-02-29 12:00 by simenpeng[未注册用户]
我想邮件菜单事根据绑定Gridview的数据源中某一项而再次绑定生成的在你的代码中要如何修改?```

#61楼[楼主]  回复 引用 查看   

2008-02-29 17:53 by webabcd      
@simenpeng
目前这个控件无法实现此功能
不过它可以添加静态链接或者调用某个按钮的事件

#62楼  回复 引用   

2008-04-14 22:30 by chp008[未注册用户]
前台代码如下:
<div>
<yyc:SmartGridView ID="sgv" runat="server" DataSourceID="ObjectDataSource1" ContextMenuCssClass="RightMenu"
AutoGenerateColumns="false" OnRowCommand="sgv_RowCommand">
<Columns>
<asp:BoundField DataField="no" HeaderText="序号" SortExpression="no" >
<itemstyle width="100px" />
</asp:BoundField>
<asp:BoundField DataField="name" HeaderText="名称" SortExpression="name" >
<itemstyle width="100px" />
</asp:BoundField>
<asp:BoundField DataField="no" HeaderText="序号" SortExpression="no" >
<itemstyle width="100px" />
</asp:BoundField>
<asp:BoundField DataField="name" HeaderText="名称" SortExpression="name" >
<itemstyle width="100px" />
</asp:BoundField>
<asp:BoundField DataField="no" HeaderText="序号" SortExpression="no" >
<itemstyle width="100px" />
</asp:BoundField>
<asp:BoundField DataField="name" HeaderText="名称" SortExpression="name" >
<itemstyle width="100px" />
</asp:BoundField>
<asp:TemplateField>
<itemstyle cssclass="hidden" />
<headerstyle cssclass="hidden" />
<itemtemplate>
<asp:Button id="btnRightMenuButton" runat="server" CommandName="RightMenuClick" CommandArgument='<%# Container.DataItemIndex %>' />
</itemtemplate>
<footerstyle cssclass="hidden" />
</asp:TemplateField>
</Columns>
<ContextMenus>
<yyc:ContextMenu BoundCommandName="RightMenuClick" Text="动态增加一列"/>
</ContextMenus>
</yyc:SmartGridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="Get"
TypeName="OjbData" OldValuesParameterFormatString="original_{0}"></asp:ObjectDataSource>
</div>
后台如下
public void sgv_RowCommand(object sender, GridViewCommandEventArgs e)
{
//Page.ClientScript.RegisterStartupScript(this.GetType(), "Alert", "<script>alert('Hello The World');</script>", true);
int b = 0;
}
第一次执行的时候,断点还能够跟到函数里面去.第二次点击右键菜单的时候,就出现了错误,说缺少对象。

#63楼  回复 引用   

2008-04-14 22:32 by chp008[未注册用户]
晕到,要设置EnableViewState="false" 才行.

#64楼[楼主]  回复 引用 查看   

2008-04-15 08:17 by webabcd      
@chp008
:)
是的
需要EnableViewState="false"

#65楼  回复 引用   

2008-06-14 15:37 by GoogleFans[未注册用户]
非常感谢你写了这么棒的控件,有个问题想请教一下--右键菜单怎样才能取得所选择行的标识呢?

#66楼[楼主]  回复 引用 查看   

2008-06-16 08:58 by webabcd      
@GoogleFans
现在能获取的是
// item = new contextItem("", "", "", "", "", "");
// 1-菜单项的文本
// 2-图标链接
// 3-所调用的命令按钮的ID
// 4-链接地址
// 5-链接的target
// 6-右键菜单的项的类别

如果要获取别的,需要你改一下代码

#67楼  回复 引用   

2008-06-16 17:11 by GoogleFans[未注册用户]
抱歉前面问题中没有说明白,我指的是在客户端的JS中如何取得当前右键所在行的字段值或者标识值?望赐教

#68楼[楼主]  回复 引用 查看   

2008-06-17 08:09 by webabcd      
@GoogleFans
都是客户端操作,那就更简单了
在生成的右键菜单的li中增加一个标识用的attribute

#69楼  回复 引用   

2008-11-06 14:03 by 蜻蜓_1[未注册用户]
博主,你好,NavigateUrl的链接可以是动态吗?
如下:
<yyc:ContextMenu Text="修改" NavigateUrl='Detail.aspx?id=<%#((DataRowView)Container.DataItem)["p_newid"]%>' Target="_blank"/> ,p_newid为主键,这样做了后,右键就没有菜单了,
如果把 <%#((DataRowView)Container.DataItem)["p_newid"]%>去掉后,右键菜单就又出现了,这是怎么回事?
有好的办法做成动态的NavigateUrl 吗?谢谢!

#70楼[楼主]  回复 引用 查看   

2008-11-06 18:25 by webabcd      
@蜻蜓_1
这个版本不支持这么做

你可以研究一下源代码里的js的实现方式,然后修改一下,以实现你的需求

#71楼  回复 引用   

2008-11-07 13:14 by goergechiu[未注册用户]
如何能够把要打开的页面以弹出方式打开

#72楼  回复 引用   

2008-11-07 13:15 by goergechiu[未注册用户]
加一下楼主msn,呵呵
zhaoshubin999@hotmail.com

#73楼[楼主]  回复 引用 查看   

2008-11-07 18:44 by webabcd      
@goergechiu
_blank或者window.open啊

我的msn
webabcd
hotmail
com

#74楼  回复 引用   

2009-01-15 12:22 by 张旭辉[未注册用户]
请教一下大家,下面两种方法在SmartGridView 添加右键菜单有什么区别呢?为什么第一种调试时右键点击时没有任何效果呢??
方法一、
if (!IsPostBack)
{
GridViewMerchantList.ContextMenus.Clear();
YYControls.ContextMenu MenuSelect = new YYControls.ContextMenu();
MenuSelect.Text = "查看";
MenuSelect.BoundCommandName = "Select";
YYControls.ContextMenu MenuDelete = new YYControls.ContextMenu();
MenuDelete.Text = "删除";
MenuDelete.BoundCommandName = "Delete";
GridViewMerchantList.ContextMenus.Add(MenuSelect);
GridViewMerchantList.ContextMenus.Add(MenuDelete);
}
方法二、
< Columns>
<asp:ButtonField CommandName="Select" Visible="true" HeaderText="选择" />
<asp:ButtonField CommandName="Delete" Visible="true" HeaderText="删除" />
</Columns>
<ContextMenus>
<yyc:ContextMenu Text="查看" BoundCommandName="Select" />
<yyc:ContextMenu Text="删除" BoundCommandName="Delete" />
</ContextMenus>

#75楼[楼主]  回复 引用 查看   

2009-01-16 07:28 by webabcd      
@张旭辉
因为本控件是在Init中扩展的,所以不支持后台编码方式
如果需要的话可以自己修改一下源码,把扩展逻辑往后移

#76楼  回复 引用   

2009-03-04 10:47 by YanJ[未注册用户]
请问楼主能否给菜单加个confirm提示??
刚做.NET不久,不知道从哪里着手!!

#77楼[楼主]  回复 引用 查看   

2009-03-04 12:01 by webabcd      
@YanJ
return confirm("")吗?
我写的这个正式不能写自定义js,测试版的可以

其实这个主要还是js功底,你可以看看源代码,其实原理都是相同的,熟悉了后,可以扩展自己需要的功能

#78楼  回复 引用 查看   

2011-08-27 12:22 by 海南.胡勇      
LZ的文章很少有图。

#79楼[楼主]  回复 引用 查看   

2011-08-29 08:38 by webabcd      
@海南.胡勇
:)
呵呵,被发现了,本人很懒
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 637485 +jUB+SL/Ojk=