关于自定义控件设计时如何把属性写入aspx中的研究(上)

简介: 如何通过继承GridView来修改在设计时绑定数据源时自动生成的ASP.Net代码? 具体情况是这样的,ObjectDataSource绑定到实体类,GridView帮定到ObjectDataSource,这时候,GridView会获取实体类的构架信息,并自动生成一些列,HeaderText就是实体类的属性名,是E文的,我现在想在GridView的CreateColumns方法中进行拦截这个生成过程,硬是把E文改为对应的中文。
如何通过继承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 img_a6339ee3e57d1d52bc7d02b338e15a60.gif private   static   void  SerializeControl(Control control, IDesignerHost host, TextWriter writer,  string  filter)
 2 img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif {
 3img_33d02437d135341f0800e3d415312ae8.gif    if (control == null)
 4img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif{
 5img_33d02437d135341f0800e3d415312ae8.gif        throw new ArgumentNullException("control");
 6img_105a1e124122b2abcee4ea8e9f5108f3.gif    }

 7img_33d02437d135341f0800e3d415312ae8.gif    if (host == null)
 8img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif{
 9img_33d02437d135341f0800e3d415312ae8.gif        throw new ArgumentNullException("host");
10img_105a1e124122b2abcee4ea8e9f5108f3.gif    }

11img_33d02437d135341f0800e3d415312ae8.gif    if (writer == null)
12img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif{
13img_33d02437d135341f0800e3d415312ae8.gif        throw new ArgumentNullException("writer");
14img_105a1e124122b2abcee4ea8e9f5108f3.gif    }

15img_33d02437d135341f0800e3d415312ae8.gif    if (control is LiteralControl)
16img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif{
17img_33d02437d135341f0800e3d415312ae8.gif        writer.Write(((LiteralControl) control).Text);
18img_105a1e124122b2abcee4ea8e9f5108f3.gif    }

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

28img_105a1e124122b2abcee4ea8e9f5108f3.gif    }

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

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

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

55img_105a1e124122b2abcee4ea8e9f5108f3.gif    }

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

64img_33d02437d135341f0800e3d415312ae8.gif        else
65img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif{
66img_33d02437d135341f0800e3d415312ae8.gif            text3 = GetTagName(control.GetType(), host);
67img_105a1e124122b2abcee4ea8e9f5108f3.gif        }

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

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

84img_05dd8d549cff04457a6366b0a7c9352a.gif}

从代码就可以看出来,这不就是在写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 ,然后导致一系列的方法调用。

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

我不相信神话,我只相信汗水!我不相信命运,我只相信双手!
相关文章
|
C# Windows
2000条你应知的WPF小姿势 基础篇<78-81 Dialog/Location/WPF设备无关性>
2000条你应知的WPF小姿势 基础篇<78-81 Dialog/Location/WPF设备无关性>
79 0
|
3月前
|
容器 C# 开发者
XAML语言大揭秘:WPF标记的魅力所在,让你轻松实现界面与逻辑分离,告别复杂代码!
【8月更文挑战第31天】XAML提供了一种直观且易于维护的界面设计方式,使得开发者可以专注于逻辑和业务代码的编写,而无需关心界面细节。通过数据绑定、布局管理和动画效果等特性,XAML可以实现丰富的界面交互和视觉效果。在实际开发过程中,开发者应根据具体需求选择合适的技术方案,以确保应用程序能够满足用户的需求。希望本文的内容能够帮助您在WPF应用程序开发中更好地利用XAML语言。
40 0
|
C#
WPF整理-为控件添加自定义附加属性
原文:WPF整理-为控件添加自定义附加属性 附加属性,大家都不陌生,最常见的是Canvas.Left/Canvas.Top,类似的也有Grid.Row/Grid.Column等附加属性。举个最常见的例子 需要说明的是并不是所有的附加属性都是元素放进去后才会有附加效果,上面的例子只是刚好是这种错觉的巧合情况,Grid.Row也属于这种巧合。
2116 0
QtApplets-自定义控件-5-属性研究
QtApplets-自定义控件-5-属性研究
120 0
QtApplets-自定义控件-5-属性研究
QtApplets-自定义控件-7-属性研究
QtApplets-自定义控件-7-属性研究
103 0
QtApplets-自定义控件-7-属性研究
QtApplets-自定义控件-4-属性研究
QtApplets-自定义控件-4-属性研究
137 0
QtApplets-自定义控件-4-属性研究
|
C#
艾伟_转载:WPF/Silverlight陷阱:XAML自定义控件的嵌套内容无法通过名称访问
为了说明这个问题,假定我们需要实现一个具有特殊功能的按钮控件。编写Xaml文件如下: Button> 对 Code Behind类,唯一的改动是把向导生成的基类从UserControl改成Button: public partial class XamlButton : Button{    ...
1075 0
|
C#
[WPF 容易忽视的细节] —— x:Name与Name属性
原文:[WPF 容易忽视的细节] —— x:Name与Name属性 一、前言 WPF使用XAML来对界面进行编写,界面与后台逻辑分离。我们也可以写Style、Trigger来实现一些界面效果, 这些都是通过Name来定位控件的,例如Setter.TargetName、Trigger.SourceName和Binding的ElementName等。
1112 0
|
C# 前端开发
WPF Adorner+附加属性 实现控件友好提示
原文:WPF Adorner+附加属性 实现控件友好提示 标题太空泛,直接上图   无论是在验证啊,还是提示方面等一些右上角的角标之类的效果,我们会怎么做? 这里介绍一种稍微简单一些的方法,利用附加属性和Adorner来完成。
995 0
用XAML做网页!!—框架
    本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/08/19/1271702.html,如需转载请自行联系原作者
1251 0