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

Winform CRM框架:XtraTabControl動態加載UserControl與Form的雙模式實戰

     編輯:關於.NET

在MDI主界面下承載海量業務頁籤時,靜態設計顯得僵化且難以擴展。Winform開發框架CRM模塊採用 XtraTabControl 動態加載技術,支持「用戶控件」與「普通窗體」兩種載體模式,配合反射創建、權限上下文傳遞、頁籤關閉持久化,構建高靈活、強解耦的多文檔界面架構。

一、 模式一:用戶控件動態加載(客戶360°視圖)

客戶相關信息Tab頁動態加載

1. 統一基類與接口契約

定義 BasePageControl : XtraUserControl, IPageApply,規範權限初始化、數據綁定標準:


public interface IPageApply {
    void InitFunction(LoginUserInfo userInfo, Dictionary<string, string> functionDict);
    void BindData(string customerID);
}

public partial class BasePageControl : XtraUserControl, IPageApply {
    public string CustomerID { get; set; }
    public LoginUserInfo LoginUserInfo { get; set; }
    // ...
}

2. 業務頁籤控件開發

各功能模塊(如往來記錄、合同、服務等)繼承 BasePageControl,利用 WinGridViewPager 實現列表展示,工具欄集成新增/編輯/刪除/導出操作。

往來記錄控件設計視圖


public partial class ActivityControl : BasePageControl {
    public ActivityControl() {
        InitializeComponent();
        InitDictItem();
        this.winGridViewPager1.OnPageChanged += new EventHandler(winGridViewPager1_OnPageChanged);
        this.winGridViewPager1.OnEditSelected += new EventHandler(winGridViewPager1_OnEditSelected);
        this.winGridViewPager1.OnAddNew += new EventHandler(winGridViewPager1_OnAddNew);
        // ... 其他事件綁定
    }
    // 實現 IPageApply.BindData 等方法
}

3. 主界面動態構建頁籤

根據用戶個性化配置(UserTreeSetting)與系統默認頁籤定義(SystemTree),反射創建控件實例並加入 XtraTabControl:


// 獲取用戶配置的頁籤ID列表
userPageList = BLLFactory<UserTreeSetting>.Instance.GetTreeSetting(pageCategory, LoginUserInfo.ID.ToString());
// 獲取系統默認頁籤定義
List<SystemTreeNodeInfo> propList = BLLFactory<SystemTree>.Instance.GetTree(pageCategory);

// 判斷是否顯示
private bool ContainPage(string id) {
    return userPageList == null || userPageList.Count == 0 || userPageList.Contains(id);
}

// 動態創建並添加頁籤
foreach (var nodeInfo in propList) {
    if (ContainPage(nodeInfo.ID)) {
        XtraTabPage page = new XtraTabPage { Name = nodeInfo.ID, Text = nodeInfo.TreeName, ImageIndex = i % 20 };
        BasePageControl control = CreateCustomerControl(nodeInfo.SpecialTag); // 反射創建
        if (control != null) {
            control.InitFunction(LoginUserInfo, FunctionDict); // 傳遞權限上下文
            control.Dock = DockStyle.Fill;
            page.Controls.Add(control);
        }
        this.tabCustomerRelated.TabPages.Add(page);
    }
}

// 反射創建控件實例
private BasePageControl CreateCustomerControl(string controlName) {
    string namePrefix = "WHC.CRM.UI.CustomerPage.";
    controlName = namePrefix + controlName;
    try {
        return CreateInstance(controlName, Assembly.GetExecutingAssembly().GetName().Name);
    } catch (Exception ex) { LogTextHelper.Error(ex); return null; }
}
private static BasePageControl CreateInstance(string sName, string sFilePath) {
    Assembly assemblyObj = Assembly.Load(sFilePath);
    return (BasePageControl)assemblyObj.CreateInstance(sName);
}

4. 頁籤關閉與配置持久化

處理 CloseButtonClick 事件,移除頁籤並保存用戶最新配置:


private void tabCustomerRelated_CloseButtonClick(object sender, EventArgs e) {
    this.tabCustomerRelated.TabPages.RemoveAt(this.tabCustomerRelated.SelectedTabPageIndex);
    List<string> nodeIdList = new List<string>();
    foreach (XtraTabPage page in this.tabCustomerRelated.TabPages) {
        if (!string.IsNullOrEmpty(page.Name)) nodeIdList.Add(page.Name);
    }
    BLLFactory<UserTreeSetting>.Instance.SaveTreeSetting(pageCategory, LoginUserInfo.ID.ToString(), nodeIdList);
}

二、 模式二:普通窗體動態加載(模塊管理工作台)

模塊管理工作台Tab頁加載Form

場景:一級菜單項對應獨立窗體(如產品管理、廠商管理),需在Tab中承載且保持窗體獨立性(可單獨彈出、複用邏輯)。

1. 主界面佈局

左側導航欄(NavBarControl),右側 XtraTabControl 承載內容頁。

模塊管理主界面設計視圖

2. 通用加載/激活邏輯


private void LoadTabPageForm(XtraTabControl tabcontrol, Type formType, int imageIndex) {
    bool found = false;
    XtraTabPage selectedPage = null;
    // 查找是否已打開
    foreach (XtraTabPage page in tabcontrol.TabPages) {
        if (page.Tag != null && page.Tag.ToString() == formType.Name) {
            found = true; selectedPage = page; break;
        }
    }
    if (!found) {
        selectedPage = new XtraTabPage();
        BaseDock dlg = (BaseDock)Activator.CreateInstance(formType); // 創建窗體實例
        dlg.Visible = true;
        dlg.Dock = DockStyle.Fill;
        dlg.FormBorderStyle = FormBorderStyle.None;
        dlg.TopLevel = false; // 關鍵:非頂級窗體,可嵌入容器
        dlg.InitFunction(LoginUserInfo, FunctionDict); // 傳遞權限上下文
        selectedPage.Text = dlg.Text;
        selectedPage.ImageIndex = imageIndex;
        selectedPage.Tag = dlg.GetType().Name;
        selectedPage.Controls.Add(dlg);
        tabcontrol.TabPages.Add(selectedPage);
    }
    selectedPage.BringToFront();
    tabcontrol.SelectedTabPage = selectedPage;
}

3. 菜單點擊調用


private void itemProduct_LinkClicked(object sender, DevExpress.XtraNavBar.NavBarLinkEventArgs e) {
    LoadTabPageForm(this.xtraTabMain, typeof(FrmProduct), 0);
}
private void itemManufacturer_LinkClicked(object sender, DevExpress.XtraNavBar.NavBarLinkEventArgs e) {
    LoadTabPageForm(this.xtraTabMain, typeof(FrmManufacturer), 1);
}
private void itemCompetitor_LinkClicked(object sender, DevExpress.XtraNavBar.NavBarLinkEventArgs e) {
    LoadTabPageForm(this.xtraTabMain, typeof(FrmCompetitor), 2);
}

4. 關閉釋放資源


private void xtraTabMain_CloseButtonClick(object sender, EventArgs e) {
    XtraTabPage currentPage = this.xtraTabMain.SelectedTabPage;
    BaseForm form = currentPage.Controls[0] as BaseForm;
    if (form != null) { form.Close(); form.Dispose(); }
    this.xtraTabMain.TabPages.RemoveAt(this.xtraTabMain.SelectedTabPageIndex);
}

三、 核心優勢對比

維度UserControl模式Form模式
適用場景從屬於主界面的功能分頁(如客戶詳情子模塊)獨立業務模塊,需支持單獨彈出/菜單直達
代碼復用僅限Tab容器內可同時作為MDI子窗體、獨立對話框、Tab頁使用
生命周期隨頁籤銷毀需手動 Dispose 釋放非託管資源
權限傳遞統一通過 IPageApply.InitFunction統一通過 IFunction.InitFunction(Form實現接口)

四、 總結

雙模式動態加載機制賦予框架極強的界面組織能力:UserControl模式構建聚合視圖,Form模式支撐模塊獨立演進。核心關鍵點在於 TopLevel=false 實現窗體容器化、統一接口傳遞權限上下文、反射解耦具體類型、關閉事件釋放資源。開發者可根據業務屬性靈活選擇,最大化代碼復用與界面靈活性。

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