zoukankan      html  css  js  c++  java
  • 控件开发笔记,鄙视写 LinkButton 那个傻蛋.

    1. GridView 的 LinkButton 是如何生成 形如:href="javascript:__doPostBack('ctl00$Content$gridCorner','Upload$2')" 的??

    E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\GridView.cs\7\GridView.cs

            PostBackOptions IPostBackContainer.GetPostBackOptions(IButtonControl buttonControl) {
                
    if (buttonControl == null) {
                    
    throw new ArgumentNullException("buttonControl"); 
                }
     
                
    if (buttonControl.CausesValidation) { 
                    
    throw new InvalidOperationException(SR.GetString(SR.CannotUseParentPostBackWhenValidating, this.GetType().Name, ID));
                } 

                PostBackOptions options 
    = new PostBackOptions(thisbuttonControl.CommandName + "$" + buttonControl.CommandArgument);
                options.RequiresJavaScriptProtocol 
    = true;
     
                
    return options;
            } 

    它是从 E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\DataControlLinkButton.cs\2\DataControlLinkButton.cs 而来。 注意这里是 DataControlLinkButton ,而不是 LinkButton,它继承了 LinkButton,所以在GridView上,可看作是 LinkButton。

            protected override PostBackOptions GetPostBackOptions() {
                
    if (_container != null) {
                    
    return _container.GetPostBackOptions(this); 
                }
     
                
    return base.GetPostBackOptions(); 
            }

    继续倒推,它是从 E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\LinkButton.cs\4\LinkButton.cs 发出的。

            protected override void AddAttributesToRender(HtmlTextWriter writer) { 
                
    // Make sure we are in a form tag with runat=server.
                if (Page != null) { 
                    Page.VerifyRenderingInServerForm(
    this);
                }

                
    // Need to merge the onclick attribute with the OnClientClick 
                string onClick = Util.EnsureEndWithSemiColon(OnClientClick);
     
                
    if (HasAttributes) { 
                    
    string userOnClick = Attributes["onclick"];
                    
    if (userOnClick != null) { 
                        
    // We don't use Util.MergeScript because OnClientClick or
                        
    // onclick attribute are set by page developer directly.  We
                        
    // should preserve the value without adding javascript prefix.
                        onClick += Util.EnsureEndWithSemiColon(userOnClick); 
                        Attributes.Remove(
    "onclick");
                    } 
                } 

                
    if (onClick.Length > 0) { 
                    writer.AddAttribute(HtmlTextWriterAttribute.Onclick, onClick);
                }

                
    bool effectiveEnabled = IsEnabled; 
                
    if (Enabled && !effectiveEnabled) {
                    
    // We need to do the cascade effect on the server, because the browser 
                    
    // only renders as disabled, but doesn't disable the functionality. 
                    writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                } 

                
    base.AddAttributesToRender(writer);

                
    if (effectiveEnabled && Page != null) { 
                    
    //
     
                    PostBackOptions options 
    = GetPostBackOptions(); 
                    
    string postBackEventReference = null;
                    
    if (options != null) { 
                        postBackEventReference 
    = Page.ClientScript.GetPostBackEventReference(options, true);
                    }

                    
    // If the postBackEventReference is empty, use a javascript no-op instead, since 
                    
    // <a href="" /> is a link to the root of the current directory.
                    if (String.IsNullOrEmpty(postBackEventReference)) { 
                        postBackEventReference 
    = "javascript:void(0)"
                    }
     
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, postBackEventReference);
                }
            }

    它是从 E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\WebControl.cs\4\WebControl.cs

            public virtual void RenderBeginTag(HtmlTextWriter writer) {
                AddAttributesToRender(writer);

                HtmlTextWriterTag tagKey 
    = TagKey; 
                
    if (tagKey != HtmlTextWriterTag.Unknown) {
                    writer.RenderBeginTag(tagKey); 
                } 
                
    else {
                    writer.RenderBeginTag(
    this.TagName); 
                }
            }

    。。

    如果想给GridView 中的 LinkButton 的 Hreft 添加 Javascript 代码.代码是不能包含 空格的, 否则,它会被解析成 %20, 很讨厌, 而且它会先执行 Href 再执行 onclick . 如果在不用 Href 属性,即不执行

    javascript:__doPostBack('ctl00$Content$gvCon','YourCommand$0'); 

    在 RowDataBound 里先设置 Href 属性: LinkButton.Attribute["href"]="" .再添加 onclick 属性.

    如果是在命令按钮之前添加完自定义脚本,那么,就非常不好玩了.暂无好法.

    1.LinkButton文字替换成 A 标签. 给 A标签添加 自定义脚本.

    2.不用LinkButton.ImageButton就没有问题嘛.

    3.重写LinkButton.阻止 Href 被Url编码.

    为什么 Href 不能直接设置呢. 贴一下代码.就说明 写 LinkButton 的为什么是傻蛋了.

    protected override void AddAttributesToRender (HtmlTextWriter writer)
    {
         
    if (Page != null)
         {
              Page.VerifyRenderingInServerForm(
    this);
         }
         
    string str0 = Util.EnsureEndWithSemiColon(OnClientClick);
         
    if (base.HasAttributes)
         {
              
    string value = base.Attributes["onclick"];
              
    if (value != null)
              {
                   str0 
    = str0 + Util.EnsureEndWithSemiColon(value);
                   
    base.Attributes.Remove("onclick");
              }
         }
         
    if (str0.Length > 0)
         {
              writer.AddAttribute(HtmlTextWriterAttribute.Onclick, str0);
         }
         
    bool flag1 = base.IsEnabled;
         
    if (Enabled && !flag1)
         {
              writer.AddAttribute(HtmlTextWriterAttribute.Disabled, 
    "disabled");
         }
         
    base.AddAttributesToRender(writer);
         
    if (flag1 && (Page != null))
         {
              PostBackOptions options 
    = GetPostBackOptions();
              
    string text3 = null;
              
    if (options != null)
              {
                   text3 
    = Page.ClientScript.GetPostBackEventReference(options, true);
              }
              
    if (string.IsNullOrEmpty(text3))
              {
                   text3 
    = "javascript:void(0)";
              }
              writer.AddAttribute(HtmlTextWriterAttribute.Href, text3);
         }
    }
     

    如果你提前给 LinkButton 设置了 Href 属性.  它会先在 base.AddAttributesToRender(writer) 里生成所有的属性.贴WebControl.AddAttributesToRender 的主要代码.

     if (attrState != null)
         {
              AttributeCollection collection1 
    = Attributes;
              IEnumerator enumerator1 
    = collection1.Keys.GetEnumerator();
              
    while (enumerator1.MoveNext())
              {
                   
    string name = (string) enumerator1.Current;
                   writer.AddAttribute(name, collection1[name]);
              }
         }

    LinkButton 的 AddAttributesToRender 会二次生成 Href , 所以,直接给 LinkButton 赋 Href 会生成两个 Href 标签 . 狂晕啊.我顶他个肺!

    我在重写 LinkButton 时只能调用父类的 AddAttributesToRender ,但是,还需要爷类的 AddAttributesToRender , 如何在孙类调用爷类的 AddAttributesToRender 呢,我想了半天也想不出来. 谁能告诉我! 在孙类写  (this as WebControl).AddAttributesToRender(writer); 会出现死循环.因为它会一直往下调用,在孙类调用爷类的方法,在爷类执行的时候又去查找被Override 的子类的方法.导致死循环.

    这里也能表现出:用组合而不用继承的好处.组合更灵活!

    ...故事似乎还没完...

    alarm   作者:NewSea     出处:http://newsea.cnblogs.com/    QQ,MSN:iamnewsea@hotmail.com

      如无特别标记说明,均为NewSea原创,版权私有,翻载必纠。欢迎交流,转载,但要在页面明显位置给出原文连接。谢谢。
  • 相关阅读:
    saltstack源码详解一
    linux的yum报错
    django restframework
    列表生成式
    面向对象的封装
    linux对于zombie的处理
    Flask学习目录
    #1_两数之和
    LeetCode入门
    Struts2(一)——基本使用
  • 原文地址:https://www.cnblogs.com/newsea/p/1536317.html
Copyright © 2011-2022 走看看