日期:2010-10-27 浏览次数:20685 次
  为了设置复合控件的外观,复合控件必须提供一些样式属性,尤其是针对子控件的样式属性。在本文中,我们将重点介绍为复合控件实现样式属性的两种方法。
  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()); 
    ......
   }
 }
  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) ] 
<