All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
在GridView中实现数据并列显示_[Asp.Net教程]
网页的新颖效果 斜着滚动的marquee_[Html教程]
SQL,UPDATE如何工作_mssql学习_编程技术
在ADO.NET中用参数化查询缩短开发时间_.net资料_编程技术
ASP.NET技巧:错误处理封装_[Asp.Net教程]
visit c++中Connection与Recordset
SQL Server 索引基础知识(2)----聚集索引,非聚集索引_[SQL Server教程]
在ASP.NET,Atlas中调用Web,Service—批量调用以提高效率_[Asp.Net教程]
select控件在Mozilla和Opera中的问题_JavaScript技术_编程技术
asp.net2.0服务器控件之CheckBox控件
Reading number is top 10 pictures
胸部遭到偷窥的女人们
西方气质的东方美女3
身材野火台灣美女1
The real super beauty10
Sora aoi after swimming
全身蕾丝丝质美臀
Tie a large font of mouse
India's national beauty of the college students
Sora aoi mirror memorial classics5
西游日记1
Download software ranking
Boxer's Top ten classic battle8
XML+Web+Service开发教程
少妇苏霞全本
艳兽都市
Photoshop 8.0图象编辑软件
I for your crazy
Ashlynn Video3
Unix video tutorial10
Eclipse 4.2.1 For Win32
The cock of the Grosvenor LTD handsome
delv published in(发表于) 2014/1/10 6:24:09 Edit(编辑)
ASP.NET,2.0服务器控件之复合控件样式_[Asp.Net教程]

ASP.NET,2.0服务器控件之复合控件样式_[Asp.Net教程]

ASP.NET 2.0服务器控件之复合控件样式_[Asp.Net教程]

为了设置复合控件的外观,复合控件必须提供一些样式属性,尤其是针对子控件的样式属性。在本文中,我们将重点介绍为复合控件实现样式属性的两种方法。

  1、上传部分样式属性

  在为复合控件实现样式属性之前,读者应首先了解"样式冒泡"的基本概念。样式冒泡多用于实现复合控件的样式属性。由于在复合控件中包含多个子控件,因此,这些子控件的样式属性可能在一定情况下,干扰复合控件的样式属性,引起样式属性混乱。为了更加明确的定义复合控件的样式属性,可以采取将子控件的样式属性上传为顶级样式属性的方法,这就是所谓的"样式冒泡"。

  通常情况下,开发人员可能面对两种情况:一种是上传子控件中少数样式属性,另一种是上传子控件中所有样式属性。本小节只介绍针对第一种情况的实现方法,而另外一种将在后面一节中进行讲解。

  本节说明的这种实现样式属性的方法,其关键是通过为子控件的Attributes指定键/值对,引入样式属性,由此将子控件的样式属性上传为复合控件顶级属性。为了方便读者理解这一方法,下面列举了一个典型应用。

  在本示例中,实现了一个复合控件MyControl,其子控件集合中包括一个Table控件。当前,需要将Table子控件的样式属性CellPadding和Border上传为MyControl的顶级样式属性。具体源代码如下所示。


public class MyControl : CompositeControl{
 // 相关代码 ......
 // 定义初始值

 private int _cellPadding = 0;
 private int _border = 1;
 ......
 // 定义样式属性,它和Table控件的样式属性CellPadding和Border类似
 public int CellPadding{
  get { return _cellPadding; }
  set { _cellPadding = value; }
  // 实现属性Border
  public int Border{
   get { return _border; }
   set { _border = value; }
   ......
   // 重写CreateChildControls方法
   protected override void CreateChildControls() {
    //相关代码
    ......
    Table t = new Table(); //将前面定义的属性添加到键/值对中   
    t.AddAttributes.Add("CellPadding",_cellPadding.ToString());
    t.AddAttributes.Add("Border",_border.ToString());
    ......
   }
 }


  以上代码显示了MyControl的一些关键源代码,其重点在于说明实现部分样式属性冒泡的关键步骤。(1)初始化顶级样式属性的字段,如果有必要可以定义初始值。(2)定义与需要升级的子控件的样式属性相同名称的属性。上面的代码中定义了属性CellPadding和Border。(3)在子控件的Attributes的键/值对中引入第2步中定义的属性。

  当设置MyControl中的样式属性CellPadding和Border的属性值时,实际是设置Table子控件的CellPadding和Border的属性值。通过以上3个关键步骤就可实现样式冒泡。

  如果读者仔细观察可以发现,以上介绍的这种实现样式冒泡的方法存在一些问题:一、这种方法只适用于升级子控件中少数样式属性。如果需要将子控件的所有样式属性都升级,而仍然使用这种方法,则实现起来非常繁琐,容易产生错误。二、所实现的样式属性缺乏逻辑性和组织性。在某种情况下,例如,多个子控件的同一样式属性都需要升级为顶级属性,这时使用该方法将会引起混乱。

  为了解决这些问题,下面介绍一种上传子控件全部样式属性的实现方法。

  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[i] != 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>


  下面列举了示例应用效果图。



图1 效果图


  如图1所示,复合控件中的文本框和按钮外观由ButtonStyle和TextBoxStyle属性设置。读者可以如同设置单个控件的样式那样,设置文本框和按钮的样式。当然,这些属性必须包含在<ButtonStyle>和<TextBoxStyle>标记中。这是必须牢记的。

  3、小结

  本章介绍了为复合控件实现样式属性的具体方法,其中包括上传部分样式属性和上传全部样式属性等。对于开发人员而言,需要根据具体情况选择使用不同的方法。通常而言,对于简单的复合控件,建议使用上传部分样式属性的方法;而对于功能复杂的复合控件而言,则建议使用上传全部样式属性。
作者:金属边缘 来源:天极开发





添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.