关于自定义控件设计时如何把属性写入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类
 1 private  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 ,然后导致一系列的方法调用。

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

我不相信神话,我只相信汗水!我不相信命运,我只相信双手!

本文转自大石头博客园博客,原文链接:http://www.cnblogs.com/nnhy/archive/2007/04/05/701485.html,如需转载请自行联系原作者
目录
打赏
0
0
0
0
20
分享
相关文章
通义万相2.2开源!可一键生成电影感视频
今天,通义万相团队正式开源推出Wan2.2,这是Wan系列视频生成模型家族的最新成员。最新的Wan2.2模型是业界首个使用MoE架构的视频生成基础模型,两个专家模型分别关注生成视频的整体布局和画面细节的完善,在同参数规模下,可节省约50%的计算资源消耗。Wan2.2模型首创「电影级美学控制系统」,将‘光影密码’、‘构图法则’、‘色彩心理学’编码成了这60多个直观的参数,将光影、色彩、镜头语言装进生成模型,实现电影级质感视频生成。
1923 14
通义万相2.2开源!可一键生成电影感视频
Qwen3 双弹发布!Qwen3-Coder + Instruct 更新版来袭
通义千问团队近日发布Qwen3系列两项重要成果:Qwen3-Coder-480B-A35B-Instruct与Qwen3-235B-A22B-Instruct-2507。前者专注于代码生成与代理能力,采用MoE架构,支持256K上下文长度,适用于Agentic Coding等任务;后者为旗舰通用模型,优化长文本与多任务处理能力,支持262,144 tokens上下文长度。两款模型均已开源,提供详细推理与微调教程,适于开发者与研究人员使用。
547 0
Cursor使用指南
Cursor是一款AI编程助手,能够帮助开发者自动生成代码、优化项目结构,并提供智能建议。它支持多模型,如Claude、GPT等,可提升编程效率。通过个性化设置与技巧,如精确需求描述、代码注释、版本控制等,开发者能够更高效地完成项目。
AI助理
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问

你好,我是AI助理

可以解答问题、推荐解决方案等