zoukankan      html  css  js  c++  java
  • Inside ASP.NET 2.0 – Controls Model(转载)

    读者基础需求:了解ASP.NET 控件设计技巧參考书目:深入剖析ASP.NET 组件设计(碁峯)、

    Developing ASP.NET Server Controls And Components(MS Press)

    Controls Model 的变革

    如你所知晓,ASP.NET 1.x 提供了设计师丰富且易用的控件群,藉由这些控件,设计师可以快速的建构网页程序,但除了这些表面上看得到的控件外,为了实现组件化设计的理想,ASP.NET 1.x 还提供了简单但完整的Controls Model ,让设计师可以自行撰写控件來增加开发速度,并藉由组件化开发模式來简化程序的复杂度与降低出错率。在ASP.NET 2.0 中,这个Controls Model 做了相当大幅度的延伸,除了相容于原來的Controls Model 外,新的Controls Model 还提供了比以往更加丰富的基础类别。在1.x 时代,老实說控件的开发模式并没有太严谨的规则,设计师只要满足最基础的要求,继承至System.Web.UI.Control 或是System.ComponentModel.Component 就能够撰写控件与组件,虽然这给了设计师高度的自由,但也间接的加重组件设计师的工作量,例如撰写资料感知控件(Data Bound Control)这种很常見的想法,每个设计师硬是得先弄清楚DataSource 与DataField 属性该如何与IDE Designer 互动,然后再撰写特定的ControlDesigner 才能完成这样的控件。为了日后不再重新撰写这些变动率低、又常用到的程序代码,有经验的设计师就会架构自己的一群基础类别。在2.0,这件事不用勞设计师费心了,ASP.NET Team 已经为常用、可制式化的控件建立一群基础类别,现在要建立一个资料感知控件,设计师只要继承至DataBoundControl 即可,不需撰写ControlDesigner 了,要建立复合式控件也只要继承至CompositeControl 就行了,这个设计不但简化了设计师的工作,同时也为控件设计模式定下一个基本的标准,可以让初学者更容易上手,让设计师将时间花费在组件真正的功能上。

    Adapter Model

    Adapter Model 首次出现于ASP.NET Mobile Controls 中,当时主要的设计概念是为了让ASP.NET 网页能够适用于不同的行动装置,图1 是该设计的概念。图1 Mobile Controls

     


    Adapter Model 采取Adapter 设计模式,将原本应该由Control 负责的Rending 动作交给另一个对象,也就是ControlAdapter 來完成,当要求到达服务器端时,ASP.NET 会判断客户端的装置类别,建立对应的ControlAdapter 來绘制控件,当然!在为了达到Rending 的动作前提下,除了真正的Rending 动作外,ControlAdapter 与Control 还建立了其它的通道,例如不同的Rending 动作需要有不同的Initialize 动作,也可能需要不同的Pre-Rending 动作,因此ControlAdapter 中定义了一群与Control 几乎相同的函式,如Init、PreRender、Render 等等。在ASP.NET 2.0 中,Adapter Model 已经被整合入Control 类别中,现在设计师可以为所有的控件建立ControlAdapter,不再仅限于Mobile Control。这个设计的目的分成远景与近需,近的是为了解决不同浏览器需要使用不同的HTML&JavaScript來绘制控件,远的是为了让Mobile与PC共享一个网页,当然!实务上这是很难达到的。

    Base Control Classes

    那到底有多少基础类别供我们应用呢?图2 列出目前笔者所观察到的类别。图2 ASP.NET 2.0 的控件基础类别Control 与WebControl 都是组件设计师熟悉的类别,接下來的DataSourceControl 是ASP.NET 2.0 新引入的Data-Binding 技术所用的基础类别,在2.0 中,DataSet 已经被SqlDataSource、AccessDataSource、OracleDataSource 等DataSource Control 所取代,而她们的基础类别就是DataSourceControl。BaseDataBoundControl 就是先前所提及的资料感知控件的基础类别,她提供了预定义的DataSourceID 属性,并为设计师预先建构了专属的ControlDesigner,因此只要继承至此类别,设计师只需专心撰写控件的程序代码,不须再耗费时间处理IDE 的相关细节。DataBoundControl 是更具体化些的基础类别,除了原有的DataSourceID 之外,另外还提供了DataMember 属性,她应该是最常用的资料感知控件基础类别,其子嗣CompositeDataBoundControl 则是用于复合式资料感知组件,如DetailsView、FormView及GridView的基础类别都是源自于此,HierarchicalDataBoundControl 是另一个支线,她是TreeView、Menu 的基础类别。最后一个基础类别是CompositeControl,用于撰写简单、不含资料感知能力的复合式控件。


    Base Control Designer Classes

    基础类别除了提供一致的实作标准外,更好的是她们预先配备了标准的ControlDesigner 來处理IDE 细节,图3 是这些基础类别所配备的基础ControlDesigner 。。图3 ASP.NET 2.0 的控件基础ControlDesigner 读者们应该可以由名称來对应出那个基础类别所用的ControlDesigner。

     


    Designer Actions

    初用VWD 或VS.NET 2005 的设计师应该都对其新的设计接口感到方便或是累赘,不管是那种感觉,至少新的设计模式真的让我们减少在WebForm 与属性盘上來回的次数, 如4 是这个新花招的截图。图4 ASP.NET 2.0 的新界面

     


    Microsoft 将此技术称为Smart Task(Smart Tag 之毒?),简单的說就是将常用的属性与工作放到这个容器中,让设计者可以方便的设定她们,不须在属性表及WebForm 上來來去去,当然!这也有缺点,这个窗口显示的速度考验着开发者的计算机速度,何时该缩、何时该展开也考验着接口设计人员的智能。那如何让自己的控件拥有这种效果呢?說來也简单,見程序1。 程序1 建立含有Smart Task 的控件

    #region Using directives 
    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Web.UI.WebControls; 
    using System.ComponentModel; 

    using System.ComponentModel.Design; 
    using System.Web.UI.Design; 
    using System.Web.UI.Design.WebControls;
    #endregion 

    namespace ClassLibrary1{ 
    public class SCCDesignerActionList : DesignerActionList {
        private ControlDesigner _designer;
            public bool ShowText {
             get { return ((SimpleDesignerTest)_designer.Component).ShowText; }
             set { ((SimpleDesignerTest)_designer.Component).ShowText = value; _designer.UpdateDesignTimeHtml();}
            } 
            public SCCDesignerActionList(ControlDesigner designer):base() {
             _designer = designer;
             }
            public void FireShowText() {
             ShowText = true
            }
            public void FireHideText() {
             ShowText = false;
             } 
            public override DesignerActionItem[] GetSortedActionItems() { 
             DesignerActionPropertyItem item = new DesignerActionPropertyItem("ShowText""Show Text","Appearence"); 
             DesignerActionMethodItem m_item; 
             if (!ShowText) 
              m_item = new DesignerActionMethodItem(this"FireShowText""Show Text","Actions"); 
             else
              m_item = new DesignerActionMethodItem(this"FireHideText""Hide Text""Actions"); 
             return new DesignerActionItem[] {item,m_item}; 
            }
        }
        
        public class SCCControlDesigner : System.Web.UI.Design.ControlDesigner { 
        public SCCControlDesigner() : base() { } 
        public override DesignerActionListCollection ActionLists { 
            get
            {
             DesignerActionListCollection actions = new DesignerActionListCollection(); 
             actions.AddRange(base.ActionLists); 
             actions.Add(new SCCDesignerActionList(this)); 
             return actions; 
            }
        
        } 

    [DesignerAttribute(typeof(SCCControlDesigner), typeof(IDesigner))]
    public class SimpleDesignerTest:WebControl {
        public bool ShowText { 
            get { 
             object o = ViewState["ShowText"];if (o != null
             return (bool)o; 
             return true;
            }
            set {ViewState["ShowText"] = value; }
        }
        protected override void Render(System.Web.UI.HtmlTextWriter writer) { 
            if(ShowText) 
             writer.WriteLine("TEST"); }
             public SimpleDesignerTest() { } 
            }
    }  

    DesignerActionPropertyItem 指的是一个属性型态的Smart Tas k,IDE 会将指定的属性显示成Smart Task,并套用该属性所有的属性编辑器。DesignerActionMethodItem 指的是一

    个选项,供使用者点选后执行某些动作,与以前的DesignerVerbs 功能相同。

    New Data Binding System

    对于ASP.NET 的使用者而言,新的Data Binding 系统无疑是2.0 中变动最大、影响也最深的设计,原來的DataSet 已经被DataSource Control 所取代,这个变动将ASP.NET 的RAD 设计模式推进一大步,DataSource 模式讲求将资料操作完全封装在DataSource Control 中,控件与其的连结仅止与资料的交换,设计师也不再需要烦恼分页、快取等琐碎的问题,甚至可以使用ObjectDataSource 來建构分布式系统。对于组件设计师來說, 新的Data Binding 模式影响不大,因为2.0 已经建构了完整的基础类别,程序2 是一个简单的Table 控件(因为Beta 1 将DataBoundControlDesigner 标示为抽象类别,因此我们得继承她才能使用)。

    程序2 SimpleTable 控件

    #region Using directives
    using System;
    using System.Collections; 
    using System.Collections.Generic;
    using System.Text; 
    using System.Web; 
    using System.Web.UI; 
    using System.Web.UI.WebControls; 
    using System.Web.UI.HtmlControls;
    using System.ComponentModel; 
    using System.Web.UI.Design.WebControls; 
    #endregion 

    namespace ClassLibrary1 { 

    public class SimpleTableDesigner : DataBoundControlDesigner { } 
    [Designer(typeof(SimpleTableDesigner))]
    public class SimpleTable:DataBoundControl {
    private IEnumerable _dataRecs; 
    protected override HtmlTextWriterTag TagKey { 
    get { return HtmlTextWriterTag.Table; } 
    }
    protected virtual void RenderHeader() { 

    if (_dataRecs != null) { 
    foreach (object item in _dataRecs) 
    HtmlTableRow row = new HtmlTableRow(); 
    foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(item)) 
    HtmlTableCell col = new HtmlTableCell(); 
    col.Controls.Add(new LiteralControl(prop.Name)); 
    row.Controls.Add(col);
    }
    Controls.Add(row);
    break
    }
    }


    protected virtual void RenderRows()
        { if (_dataRecs != null)
        { 
        foreach (object item in _dataRecs)
            { HtmlTableRow row = new HtmlTableRow(); 
        foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(item)) 
            { HtmlTableCell col = new HtmlTableCell(); 
        object v = prop.GetValue(item);
        if (v != null) col.Controls.Add(new LiteralControl(v.ToString()));
        row.Controls.Add(col); } 
        Controls.Add(row); } }


    private void OnSelectCallBack(IEnumerable data) { 
        _dataRecs = data;

    protected void RetrieveData() {
        DataSourceView view = GetData(); 
        if(view != null
            view.Select(DataSourceSelectArguments.Empty, new DataSourceViewSelectCallback(OnSelectCallBack)); 


    public override void DataBind() { 
        ClearChildControlState(); Controls.Clear();
        RetrieveData();
        RenderHeader();
        RenderRows();
        ChildControlsCreated = true
        TrackViewState();


    protected override void OnPreRender(EventArgs e) { 
        if (_dataRecs == null
    DataBind(); 
    base.OnPreRender(e); 


    public SimpleTable() { }

    } } 

    Non Visual Controls

    ASP.NET 2.0 取消了Component Tray ,这代表着Component 在ASP.NET 2.0 中将完全失去RAD 能力,取而代之的是类似DataSource Control 类的非可视型组件,就实务上來說,Non Visual Control 还是一个控件,差别在于IDE 如何看待她,要将某个控件标示为Non Visual Control ,只要配上NonVisualControl Attribute 即可。

    [NonVisualControl(true)] 

    截至目前为止,我仍未发现该Attribute 会对IDE 造成何种影响,或许日后正式版时该Attribute 会用于另一种设计,让Non Visual Control 不会影响到设计版面。

    Web Parts

    2.0 将原本于SharePoint 上的Web Parts 整合进來,许多初次接触Web Parts 的朋友反应都很正面,这个技术可以让我们与组件化设计模式更贴近,在组件设计上,撰写一个自订的Web Parts 也很容易,程序3 是个简单的范例,她也同时展示了如何使用Web Parts 的Connection 技术。程序3

    #region Using directives  
    using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.Security.Permissions; 
    using System.Web.UI;  
    using System.Web.UI.WebControls;  
    using System.Web.UI.WebControls.WebParts;  
    using System.ComponentModel;  
    #endregion 
     
    namespace ClassLibrary1{  
    public class MySimpleWebPart:WebPart
     {  
    public override bool AllowEdit
     {  
    get { return true; }
    set {base.AllowEdit = value; }

    public string Text { get { object o = ViewState["Text"]; 
    if (o != nullreturn (string)o; 
    return String.Empty; } 
    set { ViewState["Text"] = value; }
    }
    [WebBrowsable,Personalizable(PersonalizationScope.User)] 
    public string TestVeriable { get { return "TEST"; } 
    set { ;}
    }

    [WebBrowsable,Personalizable,Category("Behavior")] 
    public string TestVeriable2 { get { return "TEST"; } 
    set { ;}
    }
    [ConnectionProvider("provider","provider")] 
    public object GetData() { 
    return Text; 
    }

    [ConnectionConsumer("consumer","consumer")] 
    public void SetData(object data) {
    Text = (string)data; 

    protected override void RenderContents(HtmlTextWriter writer) {
    writer.WriteLine(Text);

    public MySimpleWebPart() { }

    Client Callback

    ASP.NET 的PostBack 技术使网页程序的功能更贴近窗口程序,但仍然无法避免于PostBack 发生时画面的闪烁情况,其实这个问题一直都困扰着许多的设计师,为了让网页能在最小闪烁情况下更新,XMLHTTP 技术就应运而生,此技术运用了XML 与HTTP协议,再整合JavaScript 让网页可以在某个事件发生时更新一部份的网页,由于并非是重新向Web Server 要求网页,因此画面的闪烁情况可以减到最轻。2.0 整合了此技术,提供了一个标准的JavaScript 及ICallbackEventHandler 接口,控件只要实作此接口,并搭配上适当的JavaScript ,就能达到网页部份刷新的效果,程序10是一个简单的范例,LowcaseTextBox会将所有输入的字串转成小写,读者可以放上她及几个RadioButton或是CheckBox,当焦点由LowcaseTextBox 離开时,就可发现字串都被转成小写,你也会发现,浏览器并未重新刷新网页,也没有闪烁的情况。程序10 LowcaseTextBox

    #region Using directives 
    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.ComponentModel; 
    using System.Web.UI; 
    using System.Web.UI.WebControls; 
    #endregion 
    namespace ClassLibrary1{ 

    public class LowcaseTextBox:TextBox,ICallbackEventHandler { 

    private const string SCRIPT = 

    "<script language='JavaScript'>/n"

    "function SetText(eventarg){/n"

    "document.getElementById('%ID%').value = eventarg;/n"

    "}</script>"

    public LowcaseTextBox() { }
    protected override void AddAttributesToRender( 
    HtmlTextWriter writer) { 
    base.AddAttributesToRender(writer); 
    writer.AddAttribute( 

    HtmlTextWriterAttribute.Onchange, Page.GetCallbackEventReference( 

    this,ClientID+".value","SetText",null)); } 
    protected override void OnPreRender(EventArgs e) { 

    base.OnPreRender(e); 
    Page.ClientScript.RegisterClientScriptBlock( GetType(), ClientID, 
    SCRIPT.Replace("%ID%",ClientID)); 

    #region ICallbackEventHandler Members 
    public string RaiseCallbackEvent(string eventArgument) { 

    return eventArgument.ToLower(); }

    #endregion

    } } 

    Still Running

    ASP.NET 2.0 仍在开发中,可以预期的是Web Parts 部份会持续的加强,许多更方便的基础类别也会一一的加入,相信在2.0 推出后,在控件市场上一定会出现相当多且方便的控件。

  • 相关阅读:
    CentOS下MySQL的彻底卸载
    cent 7.0 安装mysql
    centos 安装mysql Package: akonadi-mysql-1.9.2-4.el7.x86_64 (@anaconda)
    使用注解配置SQL映射器
    bean
    转:最简日志打印规范
    快速搭建sonar代码质量管理平台
    (转)Where与Having的总结
    一个问题,日后会写为什么贴出来
    hive Tutorial
  • 原文地址:https://www.cnblogs.com/chenying99/p/2199226.html
Copyright © 2011-2022 走看看