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

XAF (eXpressApp Framework) 自訂屬性編輯器實戰:樹狀下拉選單

     編輯:關於.NET

DevExpress XAF 根據業務類別屬性型別自動產生 UI 編輯器(字串→文字方塊、DateTime→日期選擇器、Enum→下拉清單、關聯物件→Lookup 下拉)。當內建編輯器無法滿足需求(如:一對多關聯需以樹狀結構呈現),需自訂 PropertyEditor。本文完整示範繼承 ASPxObjectPropertyEditorBase 實現樹狀下拉編輯器的全過程。

一、XAF 屬性編輯器體系

常用 Web 編輯器對應表:

屬性型別預設編輯器UI 呈現
StringASPxStringPropertyEditor文字方塊
Int32ASPxIntPropertyEditor數字輸入框
BooleanASPxBooleanPropertyEditor核取方塊
DateTimeASPxDateTimePropertyEditor日期選擇器
EnumASPxEnumPropertyEditor下拉清單
關聯物件 (BaseObject)ASPxLookupPropertyEditor下拉清單 (含搜尋)

編輯器對應關係儲存於 .xafml 模型檔(Application/Views/DetailView/Items/PropertyEditor 或 BOModel/Class/Member 節點),可透過模型編輯器視覺化修改。

模型編輯器 - View 層級 模型編輯器 - BOModel 層級

二、繼承層級選擇


PropertyEditor (抽象基類)
└── ASPxPropertyEditor (Web 專用)
    └── ASPxObjectPropertyEditorBase (物件型別編輯器基類)
        └── ASPxLookupPropertyEditor (內建 Lookup,使用 ASPxComboBox)

關鍵決策:ASPxLookupPropertyEditor 內部使用 ASPxComboBox,無法承載樹狀控制項。因此繼承 ASPxObjectPropertyEditorBase,自行構建包含 ASPxTreeList 的下拉編輯器。

三、完整實作程式碼


[PropertyEditor(typeof(object), false)] // 註冊至模型編輯器,支援所有物件型別
public class ASPxTreePropertyEditor : ASPxObjectPropertyEditorBase
{
    private WebLookupEditorHelper _helper;

    public ASPxTreePropertyEditor(Type objectType, IModelMemberViewItem model)
        : base(objectType, model)
    {
        SkipEditModeDataBind = true; // 手動控制資料繫結
    }

    // 1. 建立編輯模式控制項:回傳自訂下拉樹狀控制項
    protected override WebControl CreateEditModeControlCore()
    {
        return CreateTreeDropDown();
    }

    private TreeDropDown CreateTreeDropDown()
    {
        var treeDropDown = new TreeDropDown();
        // 2. 透過 Helper 取得關聯物件集合作為資料來源
        treeDropDown.TreeList.DataSource = _helper.CreateListView(CurrentObject).CollectionSource.List;
        treeDropDown.TreeList.KeyFieldName = "Oid";
        treeDropDown.TreeList.ParentFieldName = "Parent!Key"; // 遞迴關聯欄位
        treeDropDown.TreeList.ClientInstanceName = "TreeList";
        treeDropDown.TreeList.Width = Unit.Percentage(100);
        treeDropDown.ClientInstanceName = "DropDownEdit";
        treeDropDown.TreeList.PreviewFieldName = "Name";
        treeDropDown.TreeList.Columns.Add(new TreeListTextColumn { FieldName = "Name", Caption = "名稱" });
        treeDropDown.ReadOnly = true; // 僅選擇,不直接編輯樹節點
        treeDropDown.TreeList.SettingsBehavior.AutoExpandAllNodes = true;
        treeDropDown.TreeList.CustomCallback += TreeList_CustomCallback; // 節點點選回呼
        return treeDropDown;
    }

    // 7. 客戶端節點點選 → 伺服器回呼 → 更新屬性值
    void TreeList_CustomCallback(object sender, TreeListCustomCallbackEventArgs e)
    {
        ((TreeDropDown)Editor).Value = _helper.GetObjectByKey(CurrentObject, e.Argument);
        EditValueChangedHandler(sender, EventArgs.Empty); // 通知 XAF 值已變更
    }

    // 6. Setup 階段建立 Helper(區分持久/非持久屬性)
    public override void Setup(ObjectSpace objectSpace, XafApplication application)
    {
        base.Setup(objectSpace, application);
        _helper = MemberInfo.IsPersistent
            ? new WebLookupEditorHelper(application, objectSpace, MemberInfo.MemberTypeInfo, Model)
            : new WebLookupNonPersistentEditorHelper(application, objectSpace, MemberInfo.MemberTypeInfo, Model);
    }
}

// 3. 自訂下拉控制項:繼承 ASPxDropDownEdit,內嵌 ASPxTreeList 模板
public class TreeDropDown : DevExpress.Web.ASPxEditors.ASPxDropDownEdit
{
    private readonly ASPxTreeList _treeList = new ASPxTreeList();
    public ASPxTreeList TreeList => _treeList;

    public TreeDropDown()
    {
        // 4. 實作 ITemplate 將 TreeList 放入下拉視窗
        DropDownWindowTemplate = new TreeListTemplate(_treeList);
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        // 5. 註冊客戶端腳本:節點點選 → 設定下拉文字/值 → 關閉下拉 → 觸發伺服器回呼
        const string script = @"
            ";
        RegisterClientScriptBlock("TreeDropDownScript", script);
        TreeList.ClientSideEvents.NodeClick = "RowClickHandler";
    }

    // 5. ITemplate 實作
    private class TreeListTemplate : ITemplate
    {
        private readonly ASPxTreeList _treeList;
        public TreeListTemplate(ASPxTreeList treeList) { _treeList = treeList; }
        public void InstantiateIn(Control container) { container.Controls.Add(_treeList); }
    }
}

四、效果展示

樹狀下拉編輯器運行效果

下拉展開顯示完整樹狀階層,支援展開/摺疊、搜尋、節點選取回填。

五、關鍵技術點總結

  1. [PropertyEditor] 屬性:讓編輯器出現在模型編輯器下拉清單中。
  2. SkipEditModeDataBind = true:XAF 預設會自動繫結資料,自訂控制項需手動控制繫結時機。
  3. WebLookupEditorHelper:XAF 內建輔助類別,封裝了關聯物件查詢、ListView 建立、金鑰取得等邏輯,勿自行重造輪子。
  4. ASPxDropDownEdit + ITemplate:標準模式嵌入任意控制項至下拉面板。
  5. 客戶端 NodeClick + PerformCallback:ASPxTreeList 無伺服器端節點點選事件,需透過 JS 觸發回呼更新值。
  6. EditValueChangedHandler:通知 XAF 屬性值已變更,觸發驗證、儲存等後續流程。

六、原始碼下載

完整 VS 2010 方案 (XAF 10.1.4) 含示例模組、資料庫自動建立:
XAF_TreePropertyEditor.rar

結語

XAF 的屬性編輯器擴充機制雖有一定學習曲線,但遵循「從外而內、由框架引導」的實作順序(註冊屬性 → 建立控制項 → 模板嵌入 → 客戶端腳本 → 伺服器回呼 → Helper 整合),即可將任意複雜的 UI 需求無縫整合進自動化生成的業務介面中。此樹狀下拉編輯器模式可直接套用至組織架構、產品分類、權限樹等所有遞迴階層資料選擇場景。

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