.net控件开发(六)之深究控件样式

 

   前言:

上节中已讲述了呈现原理,我们在开发自已控件时,重写了Render方法来创建自定义输出,ASP.net给控件开发者提供了编程方式控制样式的途径。样式控制控件的可视化外观。如果您开发支持样式的控件,则从 System.Web.UI.WebControls.WebControl 派生,它将样式作为强类型属性(例如 FontHeightWidth 等)公开并为使用样式属性提供方法

概要:

1.样式概述,了解控件样式属性的创建方法

2.操作ControlStyle的几种方法

3WebControl是如何把样式生成委托给ControlStyle属性的

4.样式的状态管理

  5.重写样式属性

6.实现自定义类型化样式

正题

一.样式概述:样式是如何工作的

我们都知道在webcontrol类中已经内含了许多样式属性,这些属性由生成的html元素的可视化外观。WebControl类的样式功能封装在controlstyle属性中,样式属性实际上是ControlStyle属性的子属性。我们来看看示例就清楚了,这段代码包含了webcontrol BorderColor属性的定义。

public virtual Color BorderColor
{
    
get
    
{
        
if (!this.ControlStyleCreated)
        
{
            
return Color.Empty;
        }

        
return this.ControlStyle.BorderColor;
    }

    
set
    
{
        
this.ControlStyle.BorderColor = value;
    }

}

 

其中的this.ControlStyle.BorderColor中,从这里可以看出BorderColor的内部属性,那么我们有必要来看看ControlStyle的源代码,它是如何实现的。一步一步的解析其实现

public Style ControlStyle
{
//定义一个ControlStyle属性
    get
    
{
        
if (this.controlStyle == null)
        
{
            
this.controlStyle = this.CreateControlStyle();
            
if (base.IsTrackingViewState)
            
{
                
this.controlStyle.TrackViewState();
            }

            
if (this._webControlFlags[1])
            
{
                
this._webControlFlags.Clear(1);
                
this.controlStyle.LoadViewState(null);
            }

        }

        
return this.controlStyle;
    }

}


protected virtual Style CreateControlStyle()
{
//定义CreateControlStyle方法
    return new Style(this.ViewState);
}

 

ControlStyle是一个只读属性,返回一个Style类型,当第一次访问该属性的时候被创建。其实现过程:当controlStyle不存在时,我们就调用了CreateControlStyle方法去创建一个Style类型,然后,执行视图状态跟踪任务,其具体过程由Style类所提供的TrackViewState方法来完成。然后加载视图状态。

对于上述代码,我们来了解两点:

1.为什么是由Style类提供的TrackViewState方法完成呢。我们接下来看看如过程:

 ControlStyle我们调用了this.controlStyle.TrackViewState()方法,而其中的TrackViewState方法调用的是StyleTrackViewState方法:

伪代码如下:style中的TrackViewState方法

protected internal virtual void TrackViewState
{
    
        
this.ViewState.TrackViewState();
  
}

 

2.那么我们来看看CreateControlStyle为我们做了什么。

CreateControlStyle方法的默认实现返回一个Style对象,调用其Style的构造函数,接收一个ViewState状态包,那么ViewState是在WebControl是如何实现的呢,
protected virtual StateBag ViewState
{
    
get
    
{
        
if (this._viewState == null)
        
{
            
this._viewState = new StateBag(this.ViewStateIgnoresCase);
            
if (this.IsTrackingViewState)
            
{
                
this._viewState.TrackViewState();
            }

        }

        
return this._viewState;
    }

}

 

它去实例化一个StateBag,创建一个状态包实例,再判断其视图状态是否跟踪了其视图状态,在这里是确保视图被正确保存到了ViewState中。它是一个虚方法,所以我们可以在派生的控件中可以重载其方法来创建并返回一个自定义的Style类的自定义样式。

ControlStyle属性返回的的类型是System.Web.UI.WebControls.Style类,而Style实现了样式属性并有内建了状态管理和生成功能。

伪代码:

public class Style : Component, IStateManager
{    
…}

 

二.操作ControlStyle的几种方法

为了操作ControlStyle属性,WebControl定义了三种方法。

1.CreateControlStyle 自定义控件可以重载该方法来修改样式属性的默认值或为ControlStyle属性创建一个新的类型化样式。

格式:

protected virtural Style CreateControlStyle()

创建由WebControl类在内部用来实现所有与样式有关的属性的样式对象。
  

注意:因为WebControl不会自动保存ControlStyleViewState,所以如果要重写CreateControlStyle,那么最好按默认的策略,ViewState作为Style保存数据的地方:

示例:

protected override Style CreateControlStyle()
{
   
return new TableStyle(ViewState);
}

 

1. ApplyStyle把上传给该方法的样式中设置的样式属性复制到控件自已的ControlStyle中。

格式:

public void ApplyStyle(Style s)

将指定样式的所有非空白元素复制到服务器控件,改写控件的所有现有的样式元素。其中s表示要复制的样式。

示例:
开始:如下

 

Style style = new Style();
        style.BorderColor 
= Color.Red;
       
this.controlTable.ApplyStyle(style);//这里的controlTable是一个自定义控件
      应用样式后:
             

1.MergeStyle 从上传给该方法的样式中复制样式属性到控件自已的ControlStyle中,即复制那些指定的样式中设置的而不是在ControlStyle中设置的属性。

格式:

public void MergeStyle(Style s) 
   
  
  将指定样式的所有非空白元素复制到服务器控件,但不改写该控件现有的任何样式元素。其中s表示要复制的样式。

示例:

开始:如下

 
Style style = new Style();

        style.BorderColor 
= Color.Red;

this.controlTable.MergeStyle(s);

应用后:

 

现在,就可以看出ApplyStyleMergeStyle的区别了。

三.WebControl是如何把样式生成委托给ControlStyle属性的

接下来,我们来分析WebControl是如何把样式生成后给ControlStyle属性的。在WebControlAddAttributesToRender方法中,它调用了ControlStyle 属性的AddAttributesToRender方法。

protected virtual void AddAttributesToRender(HtmlTextWriter writer)
{
  。。。。。。。。。。。。。
。。。。。
    
if (this.ControlStyleCreated && !this.ControlStyle.IsEmpty)  //是否已经创建了控件样式
    {
        
this.ControlStyle.AddAttributesToRender(writer, this);
}

。。。。。。。。。。。
。。。。
}

public bool ControlStyleCreated
{
    
get
    
{
        
return (this.controlStyle != null);
    }

}

 

前面说过。WebControl中的样式属性实际上是ControlStyle属性的子属性,ControlStyle属性 AddAttributesToRender方法实现了把这些属性作为控件标签中的HTMlCss来生成逻辑。

四.样式的状态管理

WebControl是如何把与样式相关的状态管理委托给ControlStyle属性来完成的呢?从前面我们可以看到ControlStyle属性的Style类型实现了IStateManager接口,并对自身进行状态管理。在TrackViewState,SaveViewState,LoadViewState方法中,WebControl调用了ControlStyle属性的相应方法,

为了在WebControl实现状态管理,在Style中有两个构造器,一个只有一个StateBag类型的参数,另一个没有任何参数。当在CreateControlStyle中创建控件的样式时,WebControl使用的是一个参数的构造器,把自已的ViewState传给该构造器,

protected virtual StyleCreateControlStyle()

{

    return new Style(this.ViewState);

}

Style的两个构造函数:

publicStyle(StateBag bag)

{

   。。

    GC.SuppressFinalize(this);

}

 

publicStyle() : this(null)

{

   ,。。。

}

五:重写样式属性

 样式属性的重载与其他属性的重写类似,但必须记住一点:就是对属性值的所估摸的修改必须给控件的ControlStyle属性。

 示例:

我们举一个了简单示例。

控件代码

Aspx页面:
<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register Namespace="cnblogs.sui" TagPrefix="lab" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title>无标题页</title>
</head>
<body>
    
<form id="form1" runat="server">
    
<div>
    
<lab:LabelStyle runat=server  Text="thid is labelstyle" BorderWidth=1px  ID="bl" >
    
</lab:LabelStyle>
       
</div>
    
</form>
</body>
</html>
    在构造器中,LabelStyle对基类的BorderColor设置成Color.Red,该值将委托给ControlStyle属性,通过在LabelStyle构造器中
设置基类的
BorderColor,ForeColor,把新的值传给ControlStyle属性,它把新的值传给出ControlStyle属性,该属性负责状态管理以
及样式属性的生成,如果没有把改变传到
ControlStyle那么重载的样式属性就不会控预期的那样显示。 

六.实现自定义类型化样式

 继承自Style类的类称为类型化样式。Style类可以由控件开发人员来扩展,创建一个自定义类型化样式,它重写或者添加Style类的属性。服务器控件也可以把自定义类型化样式作为ControlStyle属性的类型。例如,Table控件的ControlStyle属性就是TableStyle类型,该类型是扩展的Style,添加了例如CellPaddingCellSpacingGridLines属性等。在初步了解类型化样式属性的基本概念之后,下面列举了实现类型化样式属性的方法要点。

1.      创建一个派生类自System.Web.UI.WebControl.Style的类

2.      定义样式为控件提供属性

3.      重写Reset方法,

4.      重写AddAttributesToRender方法,产生 HTMLCSS

5.      复制定义的属性或给定样式属性合并

示例:创建一个MyPanel控件,及相关联的类型化样式MypanelStyle,这个MyPanel控件并从WebControl继承,在MyPanelStyle中设置了3个样式属性。

1BackImageUrl,用于指定背景图片的URL

     2HorizontalAlign,用于指定所添加内容的水平对其方式;

     3Wrap,用于指定是否允许对所添加的内容换行

效果如下:
 

下面是整个的源代码:

控件代码:

控件代码

Aspx页面代码:

aspx页面

类视图:

 

解说一下:MyPanel类没有什么可说的,主要解析一下MypanelStyle类。继承于Style,是创建类型化样式的关键。定义一些字段与属性没有什么可说的,主要的说一下其中的方法。

1.      重写了AddAttributesToRender方法。当控件呈现时生成相关的htmlcss

2.      重写了CopyFrom,MergeWith,Reset方法。

CopyFrom MergeWith是为了复制给定的MypanelStyle或把给定的MypanelStyle与自身合并。

重写Reset是为了删除添加到期ViewState 中的属性,
 


后记:

.net控件开发系列

1.net组件开发系列()之武术系列-----------马步功   之基本功
2.net组件开发系列()之武术系列--------太极拳  开发ajax控件
3..net组件开发系列之武术系列武术招数控件生命周期与控件事件机制
4..net控件开发系列事件处理机制三个接口两个方法
5..net控件开发(五)之深入理解控件的呈现原理


posted @ 2007-10-21 20:02  过河卒A  阅读(3232)  评论(4编辑  收藏  举报