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

Coolite (Ext.NET) TabPanel 完整應用指南:靜態、動態(伺服器/客戶端) 建立分頁與容器整合

     編輯:ASP.NET 基礎

前言

Coolite (現更名為 Ext.NET) 的 TabPanel 是建構多標籤介面的核心容器。本文整理三種建立分頁的方式:靜態宣告、伺服器端動態建立 (AjaxEvent)、客戶端動態建立 (JavaScript API),並示範如何將其他容器 (如 TreePanel) 整合為分頁內容。

1. 靜態宣告分頁 (Markup)

<ext:TabPanel ID="tabPanel" runat="server" Width="800" Height="500">
    <Tabs>
        <ext:Tab runat="server" Title="首頁" Closable="false">
            <Body>
                <p>歡迎使用系統</p>
            </Body>
        </ext:Tab>
        <ext:Tab runat="server" Title="報表" Closable="true">
            <AutoLoad Mode="IFrame" Url="Report.aspx" NoCache="true" />
        </ext:Tab>
    </Tabs>
</ext:TabPanel>

適用於固定、少量的分頁。`AutoLoad.Mode="IFrame"` 可隔離 CSS/JS,適合載入完整頁面。

2. 伺服器端動態建立 (AjaxEvent) — 避免 PostBack 清除問題

關鍵點:一般 PostBack 會導致動態建立的控制項消失,必須使用 Coolite 的 AjaxEvent 機制 (非同步回發),並在回發後重新加入控制項樹。

後端

[DirectMethod] // 或 AjaxEvent 處理函式
protected void CreateTab_Click(object sender, DirectEventArgs e)
{
    var tab = new Tab("動態新增分頁 " + DateTime.Now.ToString("HH:mm:ss"))
    {
        ID = "tab_" + Guid.NewGuid().ToString("N").Substring(0, 8),
        Closable = true,
        AutoLoad = new AutoLoadConfig
        {
            Url = "https://www.example.com",
            Mode = LoadMode.IFrame,
            NoCache = true,
            ShowMask = true,
            MaskMsg = "載入中..."
        }
    };
    
    tabPanel.Tabs.Add(tab);
    tabPanel.ActiveTab = tab; // 切換到新分頁
}

前端按鈕綁定 AjaxEvent

<ext:Button ID="btnCreateTab" runat="server" Text="新增分頁 (Server)">
    <DirectEvents>
        <Click OnEvent="CreateTab_Click" />
    </DirectEvents>
</ext:Button>

3. 客戶端動態建立 (JavaScript API) — 體驗最佳、無閃爍

純前端操作,無 PostBack,效能最好,支援即時互斥檢查 (避免重複分頁)。

JavaScript 函式

<script type="text/javascript">
function addTab(tabPanelId, tabId, url, title) {
    var tabPanel = Ext.getCmp(tabPanelId);
    if (!tabPanel) return;

    // 檢查是否已存在
    var existing = tabPanel.getComponent(tabId);
    if (existing) {
        tabPanel.setActiveTab(existing);
        return;
    }

    // 建立新分頁
    var newTab = tabPanel.add({
        id: tabId,
        title: title || url,
        closable: true,
        autoLoad: {
            showMask: true,
            url: url,
            mode: 'iframe',
            maskMsg: '正在載入...'
        }
    });
    
    tabPanel.setActiveTab(newTab);
}
</script>

按鈕觸發

<ext:Button ID="btnClient" runat="server" Text="新增分頁 (Client)">
    <Listeners>
        <Click Handler="addTab('tabPanel', 'tab_google', 'https://www.google.com', 'Google');" />
    </Listeners>
</ext:Button>

4. 將現有容器控制項 (如 TreePanel) 整合為分頁

Ext.NET 允許將任何 `Component` 動態加入 `TabPanel`,實現「分頁即容器」的彈性佈局。

<ext:TreePanel ID="treePanel" runat="server" Title="導航樹" RootVisible="false">
    <Root>
        <ext:Node Text="根節點" Expanded="true">
            <Nodes>
                <ext:Node Text="子節點 1" leaf="true" />
                <ext:Node Text="子節點 2" leaf="true" />
            </Nodes>
        </ext:Node>
    </Root>
</ext:TreePanel>

<ext:Button ID="btnAddTreeAsTab" runat="server" Text="將樹加為分頁">
    <Listeners>
        <Click Handler="
            var tabPanel = #{tabPanel};
            var tree = #{treePanel};
            var tabId = 'tab_tree';
            
            // 移除樹原本的容器 (若已渲染在別處)
            // tree.ownerCt?.remove(tree, false); 
            
            var tab = tabPanel.getComponent(tabId);
            if (!tab) {
                tab = tabPanel.add({
                    id: tabId,
                    title: '樹狀導航',
                    closable: true,
                    layout: 'fit',
                    items: [tree] // 直接將元件實例加入
                });
            }
            tabPanel.setActiveTab(tab);
        " />
    </Listeners>
</ext:Button>

5. 進階技巧與最佳實踐

分頁狀態持久化 (跨 Session)

// 儲存使用者開啟的分頁狀態到 Cookie/LocalStorage
function saveTabState(tabPanel) {
    var tabs = tabPanel.items.map(t => ({ id: t.id, title: t.title, url: t.autoLoad?.url }));
    localStorage.setItem('myTabState', JSON.stringify(tabs));
}

// 頁面載入時還原
function restoreTabState(tabPanel) {
    var state = JSON.parse(localStorage.getItem('myTabState') || '[]');
    state.forEach(t => addTab(tabPanel.id, t.id, t.url, t.title));
    if (state.length) tabPanel.setActiveTab(state[state.length-1].id);
}

IFrame 跨域通訊 (PostMessage)

// 父頁面監聽
window.addEventListener('message', function(e) {
    if (e.origin !== 'https://trusted-child.com') return;
    if (e.data.type === 'resize') {
        var iframe = document.getElementById(e.data.tabId + '_iframe');
        if (iframe) iframe.style.height = e.data.height + 'px';
    }
});

// 子頁面發送
parent.postMessage({ type: 'resize', tabId: 'tab_1', height: document.body.scrollHeight }, '*');

效能優化:延遲載入

// 僅在分頁被啟用時才載入內容
autoLoad: {
    url: 'HeavyReport.aspx',
    mode: 'iframe',
    noCache: true,
    // Ext.NET 會自動處理:非活動分頁不載入
}

常見問題排查

問題原因解決
動態分頁 PostBack 後消失一般 PostBack 不會重建動態控制項改用 DirectEvent/AjaxEvent 或客戶端建立
IFrame 內頁面無法存取父頁面 JS同源策略限制同域用 parent.xxx,跨域用 postMessage
分頁標題過長導致版面破裂CSS 未處理長文字加 CSS `.x-tab-strip-text { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; max-width: 150px; }`
大量分頁記憶體洩漏未銷毀 IFrame/Component關閉分頁時呼叫 `tab.destroy()`,或設 `autoDestroy: true`

總結

  • 靜態分頁:簡單、固定結構首選。
  • 伺服器端動態 (AjaxEvent):需依據伺服器邏輯/權限決定分頁內容時使用。
  • 客戶端動態 (JS API):最推薦,體驗流暢、無閃爍、支援即時互斥檢查、可結合 LocalStorage 持久化。
  • 容器整合:`TabPanel.add({ items: [existingComponent] })` 實現極致彈性佈局。

掌握這三種模式與進階技巧,即可駕馭 Ext.NET TabPanel 建構企業級多標籤應用介面。

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