zoukankan      html  css  js  c++  java
  • 关于自定义控件设计时如何把属性写入aspx中的研究(上)

    如何通过继承GridView来修改在设计时绑定数据源时自动生成的ASP.Net代码?

    具体情况是这样的,ObjectDataSource绑定到实体类,GridView帮定到ObjectDataSource,这时候,GridView会获取实体类的构架信息,并自动生成一些列,HeaderText就是实体类的属性名,是E文的,我现在想在GridView的CreateColumns方法中进行拦截这个生成过程,硬是把E文改为对应的中文。
    结果,在设计时和运行时都可以看到是中文的,但是aspx中就不是中文的。
    我就想问问,怎么样,才能让它在aspx中体现中文,GridView自身是怎么样把自动生成的列写入到aspx中的。

    我已经把GridView以及几个基类的源码翻了好几遍了,我肯定,我已经把CreateColumns拦截到并修改成功了,但是,它从哪里得到英文HeaderText的BoundColumn写入到aspx中的?难道自动生成列的某些过程不需要调用CreateColumns?

    经过跟踪发现:在设计时,vs会生成这个控件的两个实例,具体干什么我不知道,在取消数据源绑定或者重新绑定数据源的时候,其中一个实例B被销毁,又有新的实例被创建,如此反反复复。剩下的那个实例A,只是偶尔被调用几个方法。(有一个方法,可以在A以外的实例中,取得A实例,就是this.Site.Component as GridView。)
    原来,我所拦截的CreateColumns,都是B和后面的实例,根本就没有拦截到A,它从来不调用CreateColumns方法。在绑定数据源时,既然IDE写入到aspx的列头是英文,那么,我可以肯定,它读取的是A中的列信息,因为,除了A以外,别的所有实例都已经被我捕获到,并把列头改为了中文,所以,IDE不可能从实例A取列信息。

    但是,我有纳闷了,A从来不调用CreateColumns方法,它哪里来的列信息?

    最后只有一种可能,那就是:那些属性,是被复制过去的,或者在GridViewDesigner中创建的。
     
    这个猜想,没有得到验证,不过,在我把调用堆栈翻过几遍以后,终于发现了写入aspx的一个可疑之处:
    ControlSerializer类
     1private static void SerializeControl(Control control, IDesignerHost host, TextWriter writer, string filter)
     2{
     3    if (control == null)
     4    {
     5        throw new ArgumentNullException("control");
     6    }

     7    if (host == null)
     8    {
     9        throw new ArgumentNullException("host");
    10    }

    11    if (writer == null)
    12    {
    13        throw new ArgumentNullException("writer");
    14    }

    15    if (control is LiteralControl)
    16    {
    17        writer.Write(((LiteralControl) control).Text);
    18    }

    19    else if (control is DesignerDataBoundLiteralControl)
    20    {
    21        DataBinding binding = ((IDataBindingsAccessor) control).DataBindings["Text"];
    22        if (binding != null)
    23        {
    24            writer.Write("<%# ");
    25            writer.Write(binding.Expression);
    26            writer.Write(" %>");
    27        }

    28    }

    29    else if (control is UserControl)
    30    {
    31        IUserControlDesignerAccessor accessor = (IUserControlDesignerAccessor) control;
    32        string tagName = accessor.TagName;
    33        if (tagName.Length > 0)
    34        {
    35            writer.Write('<');
    36            writer.Write(tagName);
    37            writer.Write(" runat=\"server\"");
    38            ObjectPersistData persistData = null;
    39            IControlBuilderAccessor accessor2 = control;
    40            if (accessor2.ControlBuilder != null)
    41            {
    42                persistData = accessor2.ControlBuilder.GetObjectPersistData();
    43            }

    44            SerializeAttributes(control, host, string.Empty, persistData, writer, filter);
    45            writer.Write('>');
    46            string innerText = accessor.InnerText;
    47            if ((innerText != null&& (innerText.Length > 0))
    48            {
    49                writer.Write(accessor.InnerText);
    50            }

    51            writer.Write("</");
    52            writer.Write(tagName);
    53            writer.WriteLine('>');
    54        }

    55    }

    56    else
    57    {
    58        string text3;
    59        HtmlControl control2 = control as HtmlControl;
    60        if (control2 != null)
    61        {
    62            text3 = control2.TagName;
    63        }

    64        else
    65        {
    66            text3 = GetTagName(control.GetType(), host);
    67        }

    68        writer.Write('<');
    69        writer.Write(text3);
    70        writer.Write(" runat=\"server\"");
    71        ObjectPersistData objectPersistData = null;
    72        IControlBuilderAccessor accessor3 = control;
    73        if (accessor3.ControlBuilder != null)
    74        {
    75            objectPersistData = accessor3.ControlBuilder.GetObjectPersistData();
    76        }

    77        SerializeAttributes(control, host, string.Empty, objectPersistData, writer, filter);
    78        writer.Write('>');
    79        SerializeInnerContents(control, host, objectPersistData, writer, filter);
    80        writer.Write("</");
    81        writer.Write(text3);
    82        writer.WriteLine('>');
    83    }

    84}

    从代码就可以看出来,这不就是在写aspx嘛。只是看而已,没有确定^_^
    这个类,还有大量串行化的方法。

    至于怎么发现的……
    是这样的,我写了一个类来继承GridView,把所有可以override的方法,都override一遍,然后,重写的类里面,输出当前调用堆栈信息到一个文本文件中。然后,在ide中使用这个控件,绑定数据源,取消绑定,多试几次,就可以得到足够的日志了。
    下面是绑定到一个数据源控件时,所得到的override EnsureChildControls方法调用方法栈帧,第一个EnsureChildControls是GridView的EnsureChildControls:
    EnsureChildControls  <-  
    CompositeDataBoundControl.get_Controls  <-  
    ControlSerializer.SerializeInnerProperties  <-  
    ControlSerializer.SerializeInnerContents  <-  
    ControlSerializer.SerializeInnerContents  <-  
    ControlDesigner.GetPersistInnerHtmlInternal  <-  
    ControlDesigner.GetPersistInnerHtml  <-  
    ControlDesigner.GetPersistenceContent  <-  
    IdentityBehavior.OnBehaviorNotify  <-  
    DHTMLBehavior.Microsoft.VisualStudio.Web.Interop.Trident.IElementBehavior._Notify  <-  
    IHTMLElement.GetOuterHTML  <-  
    IdentityBehavior.GetOuterHTML  <-  
    IdentityBehavior.System.Web.UI.Design.IControlDesignerTag.GetOuterContent  <-  
    ControlDesignerSite.System.Web.UI.Design.IControlDesignerTag.GetOuterContent  <-  
    ControlDesigner.CreateClonedControl  <-  
    ControlDesigner.CreateViewControl  <-  
    ControlDesigner.CreateViewControlInternal  <-  
    ControlDesigner.get_ViewControl  <-  
    GridViewDesigner.GetDesignTimeHtml  <-  
    GridViewDesigner.GetDesignTimeHtml  <-  
    ControlDesigner.GetViewRendering  <-  
    ControlDesigner.GetViewRendering  <-  
    IdentityBehavior.GetDesignTimeHtml  <-  
    IdentityBehavior.RenderDesignTimeHtml  <-  
    IdentityBehavior.UpdateView  <-  
    IdentityBehavior.System.Web.UI.Design.IControlDesignerView.Update  <-  
    ControlDesignerSite.System.Web.UI.Design.IControlDesignerView.Update  <-  
    ControlDesigner.UpdateDesignTimeHtml  <-  
    ControlDesigner.OnComponentChanged  <-  
    ComponentChangeAction.DoAction  <-  
    BaseUndoableAction.Microsoft.VisualStudio.Web.Interop.TriDsn.IUndoAction.DoAction  <-  
    IUndoTransaction.Rollback  <-  
    ASPUndoCoordinator.CancelTransaction  <-  
    ASPUndoCoordinator.OnTransactionClosed  <-  
    DesignerTransactionCloseEventHandler.Invoke  <-  
    DesignerHost.OnTransactionClosed  <-  
    DesignerHostTransaction.OnCancel  <-  
    DesignerTransaction.Cancel  <-  
    DesignerTransaction.Dispose 
    这些方法是从下往上调用的。
    从中可以看到几个GridViewDesigner的方法,大概意思就是,我绑定数据源控件后,设计时触发ControlDesigner.UpdateDesignTimeHtml ,然后导致一系列的方法调用。

    我的研究,就到这里了,下次有空再把剩下的发上来吧。

  • 相关阅读:
    简单说说Restful API
    事务的ACID特性
    WPF DataGrid与ListView性能对比与场景选择
    WPF MVVM实现INotifyPropertyChanged数据监听
    学习Promise异步编程
    CSS单位
    Mac Docker设置国内镜像加速器
    Mac下安装Redis,附可视化工具Medis
    预告 | XPocket开源产品发布会将于1月15日正式线上直播!
    CSDN资源免费下载
  • 原文地址:https://www.cnblogs.com/nnhy/p/701485.html
Copyright © 2011-2022 走看看