首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET 2.0 復合控制項樣式屬性實作:樣式冒泡與完整樣式封裝

     編輯:關於ASP.NET

什麼是樣式冒泡?

復合控制項包含多個子控制項,每個子控制項都有自己的樣式屬性(如 ForeColor、BackColor、Font 等)。若不加處理,外部開發者無法直接在復合控制項層級統一設定這些樣式。樣式冒泡就是將子控制項的特定樣式屬性「向上提升」為復合控制項的頂層屬性,讓使用者像操作單一控制項一樣設定外觀。

兩種實作層次

情況一:僅冒泡少數屬性(屬性映射法)

適用於只需暴露子控制項少數樣式屬性的情境。核心步驟:

  1. 在復合控制項定義同名的公用屬性(如 CellPadding、Border)。
  2. 於 CreateChildControls 中建立子控制項實例。
  3. 將頂層屬性值寫入子控制項的 Attributes 集合(鍵/值對),瀏覽器渲染時自動轉為 HTML 屬性。
public class MyControl : CompositeControl
{
    private int _cellPadding = 0;
    private int _border = 1;

    public int CellPadding { get { return _cellPadding; } set { _cellPadding = value; } }
    public int Border { get { return _border; } set { _border = value; } }

    protected override void CreateChildControls()
    {
        Table t = new Table();
        t.Attributes["CellPadding"] = _cellPadding.ToString();
        t.Attributes["Border"] = _border.ToString();
        Controls.Add(t);
    }
}

缺點: 屬性分散、難以維護、多子控制項同名屬性易衝突、無法支援複雜樣式物件(如 TableItemStyle)。

情況二:冒泡子控制項所有樣式屬性(型別化樣式法)

建立繼承自 Style 的專屬樣式類別(如 MyControlStyle : Style),封裝完整樣式邏輯,再將其作為復合控制項的 ControlStyle 型別。此法解決上述所有缺點,且支援視圖狀態自動管理、樣式合併(MergeWith)、複製(CopyFrom)等進階功能。

型別化樣式實作完整範例

1. 定義專屬樣式類別

public class MyPanelStyle : Style
{
    private string _backImageUrl;
    private HorizontalAlign _horizontalAlign = HorizontalAlign.NotSet;
    private bool _wrap = true;

    public string BackImageUrl
    {
        get { return _backImageUrl; }
        set { _backImageUrl = value; }
    }
    public HorizontalAlign HorizontalAlign
    {
        get { return _horizontalAlign; }
        set { _horizontalAlign = value; }
    }
    public bool Wrap
    {
        get { return _wrap; }
        set { _wrap = value; }
    }

    protected override void FillStyleAttributes(CssStyleCollection css, IUrlResolutionService urlResolver)
    {
        base.FillStyleAttributes(css, urlResolver);
        if (!string.IsNullOrEmpty(_backImageUrl))
            css["background-image"] = "url(" + urlResolver.ResolveClientUrl(_backImageUrl) + ")";
        if (_horizontalAlign != HorizontalAlign.NotSet)
            css["text-align"] = _horizontalAlign.ToString().ToLower();
        if (!_wrap)
            css["white-space"] = "nowrap";
    }

    public override void CopyFrom(Style s)
    {
        base.CopyFrom(s);
        MyPanelStyle mps = s as MyPanelStyle;
        if (mps != null)
        {
            _backImageUrl = mps._backImageUrl;
            _horizontalAlign = mps._horizontalAlign;
            _wrap = mps._wrap;
        }
    }
    public override void MergeWith(Style s)
    {
        if (IsEmpty) { CopyFrom(s); return; }
        MyPanelStyle mps = s as MyPanelStyle;
        if (mps != null && !mps.IsEmpty)
        {
            if (!string.IsNullOrEmpty(mps._backImageUrl)) _backImageUrl = mps._backImageUrl;
            if (mps._horizontalAlign != HorizontalAlign.NotSet) _horizontalAlign = mps._horizontalAlign;
            _wrap = mps._wrap;
        }
        base.MergeWith(s);
    }
    public override void Reset()
    {
        _backImageUrl = null;
        _horizontalAlign = HorizontalAlign.NotSet;
        _wrap = true;
        base.Reset();
    }
}

2. 復合控制項使用專屬樣式

[ToolboxData("<{0}:MyPanel runat=server></{0}:MyPanel>")]
public class MyPanel : CompositeControl
{
    private MyPanelStyle _controlStyle;

    public MyPanelStyle MyPanelStyle
    {
        get
        {
            if (_controlStyle == null) _controlStyle = new MyPanelStyle();
            return _controlStyle;
        }
    }

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

    protected override void CreateChildControls()
    {
        // 這裡可建立內部子控制項,並套用 MyPanelStyle 的屬性
    }

    protected override void Render(HtmlTextWriter writer)
    {
        // 將樣式套用至最外層容器
        MyPanelStyle.AddAttributesToRender(writer, this);
        writer.RenderBeginTag(HtmlTextWriterTag.Div);
        RenderContents(writer);
        writer.RenderEndTag();
    }
}

進階技巧:子控制項樣式統一管理

若復合控制項包含多個同類子控制項(如 HeaderStyle、RowStyle、AlternatingRowStyle),可參考 GridView 模式,定義多個 TableItemStyle 型別屬性,並在 CreateChildControls 或資料繫結階段套用。

設計時支援

  • 套用 [Designer(typeof(MyPanelDesigner))] 提供自訂設計器。
  • 實作 ICompositeControlDesignerAccessor.RecreateChildControls 讓設計器即時反映屬性變更。

總結

方法適用場景優點缺點
屬性映射少數簡單屬性快速、程式碼少擴充性差、無型別安全、難維護
型別化樣式完整樣式封裝、多子控制項、需設計時支援型別安全、支援視圖狀態、樣式合併/複製、設計時友善初期程式碼較多

建議:專案初期若樣式需求簡單可用屬性映射快速原型;正式產品請採用型別化樣式,長期維護成本更低。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved