打印

[asp.net教程] asp.net 2.0服务器控件之复合控件样式2

asp.net 2.0服务器控件之复合控件样式2

2、上传全部样式属性
   
    在上一节中,说明了有关实现复合控件样式的内容,但是,那种实现方法只能实现子控件部分的样式,并且缺乏逻辑性和组织性。本小节介绍的实现复合控件样式属性的方法有效避免了以上问题。它实现了多重委托的属性,即对每个子控件分别定义width、height等样式,更进一步的讲,即实现每个子控件对应的style类型的复杂样式属性,例如,textboxstyle、buttonstyle。通过这种方式子控件的样式属性就上传为顶层属性,以便于设置子控件的外观。
   
    显而易见,实现子控件的样式属性上传的关键是实现style类型的复杂样式属性。为此,开发人员必须为复杂样式属性提供自定义视图状态管理。需要读者注意的是,复合控件的视图状态与普通控件视图状态有所不同。由于复合控件包含子控件,因此,相应的视图状态中既包括父控件的视图状态,也包括子控件对应的复杂样式属性的视图状态。例如,上文实例中控件的视图状态即包含3个部分:父控件自身的视图状态、buttonstyle的视图状态和textboxstyle的视图状态。除此之外,具体的实现过程与实现普通的复杂属性基本一致。
   
    不知读者是否还记得上一篇文章中的那个复合控件,即由一个文本框textbox和一个按钮button组成的复合控件compositeevent。在此,我们对该控件添加设置了控件的顶层样式属性buttonstyle和textboxstyle。下面列举了控件类compositeevent的源代码。
   
  using system;
  using system.web.ui;
  using system.web.ui.webcontrols;
  using system.componentmodel;
  using system.componentmodel.design;
  namespace webcontrollibrary{
   public class compositeevent : compositecontrol {
    //声明变量
    private button _button;
    private textbox _textbox;
    private static readonly object eventsubmitkey = new object();
    //声明样式变量
    private style _buttonstyle;
    private style _textboxstyle;
    //定义属性buttontext,用于指定按钮上的文字
    [bindable(true), category("appearance"), defaultvalue(""), description("获取或设置显示显示在按钮上的文字")]
   
    public string buttontext {
     get { ensurechildcontrols(); return _button.text; }
     set { ensurechildcontrols(); _button.text = value; }
    }
    //定义属性text,表示文本框的输入
   
    [bindable(true), category("appearance"), defaultvalue(""), description("获取或设置文本框输入文本")]
    public string text {
     get {
      ensurechildcontrols();
      return _textbox.text;
     }
     set {
      ensurechildcontrols();
      _textbox.text = value;
     }
    }
    // 定义buttonstyle属性
    [ category("style"), description("button的样式属性"), designerserializationvisibility(designerserializationvisibility.content), notifyparentproperty(true), persistencemode(persistencemode.innerdefaultproperty) ]
   
    public virtual style buttonstyle {
     get {
      if (_buttonstyle == null) {
       _buttonstyle = new style();
       if (istrackingviewstate) {
        ((istatemanager)_buttonstyle).trackviewstate();
       }
      }
      return _buttonstyle;
     }
    }
    //定义textstyle属性
   
    [ category("style"), description("设置textbox的样式属性"), designerserializationvisibility(designerserializationvisibility.content), notifyparentproperty(true), persistencemode(persistencemode.innerproperty) ]
   
    public virtual style textboxstyle {
     get {
      if (_textboxstyle == null) {
       _textboxstyle = new style();
       if (istrackingviewstate) {
        ((istatemanager)_textboxstyle).trackviewstate();
       }
      }
      return _textboxstyle;
     }
    }
    // 实现事件属性结构
    public event eventhandler submit {
     add { events.addhandler(eventsubmitkey, value); }
     remove { events.removehandler(eventsubmitkey, value); }
    }
    // 实现onsubmit
    protected virtual void onsubmit(eventargs e) {
     eventhandler submithandler = (eventhandler)events[eventsubmitkey];
     if (submithandler != null) {
      submithandler(this, e);
     }
    }
   
    // 重写icompositecontroldesigneraccessor接口的recreatechildcontrls方法
    protected override void recreatechildcontrols() { ensurechildcontrols(); }
     //重写createchildcontrols方法,将子控件添加到复合控件中
    protected override void createchildcontrols() {
     controls.clear();
     _button = new button();
     _textbox = new textbox();
     _button.id = "btn";
     //_button.click += new eventhandler(_button_click);
     _button.commandname = "submit";
     this.controls.add(_button);
     this.controls.add(_textbox);
    }
    // 重写onbubbleevent方法,执行事件冒泡
    protected override bool onbubbleevent(object source, eventargs e) {
     bool handled = false;
     if (e is commandeventargs) {
      commandeventargs ce = (commandeventargs)e;
      if (ce.commandname == "submit") {
       onsubmit(eventargs.empty);
       handled = true;
      }
     }
     return handled;
    }
    //重写render方法,呈现控件中其他的html代码
    protected override void render(htmltextwriter output) {
     addattributestorender(output);
     if (_textboxstyle != null) {
      _textbox.applystyle(textboxstyle);
     }
    if (_buttonstyle != null) {
     _button.applystyle(buttonstyle);
    }
    output.addattribute(htmltextwriterattribute.border, "0px");
    output.addattribute(htmltextwriterattribute.cellpadding, "5px");
    output.addattribute(htmltextwriterattribute.cellspacing, "0px");    
    output.renderbegintag(htmltextwritertag.table);
    output.renderbegintag(htmltextwritertag.tr);
    output.renderbegintag(htmltextwritertag.td);
    _textbox.rendercontrol(output);
    output.renderendtag();
    output.renderbegintag(htmltextwritertag.td);
    _button.rendercontrol(output);
    output.renderendtag();   
    output.renderendtag();
    output.renderendtag();
   }
   //复杂样式属性的状态管理,重写3个相关方法loadviewstate、  saveviewstate、trackviewstate
   
   protected override void loadviewstate(object savedstate) {
    if (savedstate == null) {
     base.loadviewstate(null);
     return;
    }
    if (savedstate != null) {
     object[] mystate = (object[])savedstate;
     if (mystate.length != 3) { throw new argumentexception("无效的viewstate"); }    
     base.loadviewstate(mystate[0]); if (mystate[1] != null) {    
       ((istatemanager)textboxstyle).loadviewstate(mystate[1]);
     }
     if (mystate[2] != null) {
      ((istatemanager)buttonstyle).loadviewstate(mystate[2]);
     }
   }
  }
   
   protected override object saveviewstate() {
    object[] mystate = new object[3];
    mystate[0] = base.saveviewstate();
     mystate[1] = (_textboxstyle != null) ? ((istatemanager)_textboxstyle).saveviewstate() : null;
     mystate[2] = (_buttonstyle != null) ? ((istatemanager)_buttonstyle).saveviewstate() : null;
     for (int i = 0; i < 3; i++) {
      if (mystate != null) { return mystate; }

     }
     return null;
    }
    protected override void trackviewstate() {
     base.trackviewstate();
     if (_buttonstyle != null) {
      ((istatemanager)_buttonstyle).trackviewstate();
     }
     if (_textboxstyle != null) {
      ((istatemanager)_textboxstyle).trackviewstate();
     }
    }
   }
  }
   
    如果读者看过前面的文章,那么应该对以上代码不陌生。限于篇幅,本文不对先前说明过的内容进行讲解,而重点说明有关样式冒泡的内容。
   
    与样式冒泡相关的内容可以分成三个部分:一是定义style类型的复杂样式属性:buttonstyle和textboxstyle;二是在render方法中为子控件应用复杂样式属性;三是实现复杂样式属性的自定义视图状态管理部分。以上三个部分的实现,实际是实现子控件样式上传过程中最为关键的三个步骤。前两个部分的实现比较简单,在此就不多加说明。下面重点说明最后一个部分的实现。
   
    第三部分主要实现复杂样式属性的自定义状态管理。在trackviewstate方法中,分别对基类、_textboxstyle和_buttonstyle调用trackviewstate。在saveviewstate方法中,首先定义一个mystate对象数组,然后按顺序将基类、textbox和button的视图状态数据保存到mystate中并返回。在loadviewstate方法中,实现将所保存的状态数据(savedstate)的第一部分加载入基类,第二部分加载给textboxstyle,第三部分加载给buttonstyle,之所以按照如此顺序加载是与saveviewstate方法中的保存顺序对应的。
   
    下面是compositeevent控件的应用代码片断。请读者注意的是:buttonstyle和textboxstyle都是作为内部嵌套形式属性而标记,用户通过设置样式属性即可完成对子控件的外观设置。
   
  <%@ page language="c#" autoeventwireup="true" codefile="default.aspx.cs" inherits="_default" %>
  <%@ register tagprefix="sample" assembly="webcontrollibrary" namespace="webcontrollibrary" %>
  <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
  <script runat="server">
  void demo1_submit(object sender, eventargs e)
  {
    lbmessage.text = "您刚才输入的是:" + demo1.text;
   }
  </script>
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head id="head1" runat="server">
  <title>为复合控件实现样式</title>
  </head>
  <body> <form id="form1" runat="server">
  <div>
  <sample:compositeevent id="demo1" runat="server" buttontext="提交" onsubmit="demo1_submit">
  <textboxstyle width="198px" height="20px" borderwidth="1px" backcolor="orange">
  </textboxstyle>
  <buttonstyle width="84px" height="24px" borderwidth="1px" borderstyle="dotted"></buttonstyle>
  </sample:compositeevent>
  <br />
  <asp:label id="lbmessage" runat="server">
  </asp:label> </div>
  </form>
  </body>
  </html>
   
    下面列举了示例应用效果图。

TOP

返回顶部
AYBlue

Processed in 0.056022 second(s), 7 queries.

当前时区 GMT+8, 现在时间是 2009-1-10 11:36 京ICP备06054220号

清除 Cookies - 联系我们 - 163K.com - Archiver - WAP