国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

轉貼自MS:擴展 TreeView 控件 (2)

2024-07-21 02:24:19
字體:
來源:轉載
供稿:網友

添加顯示和值成員屬性


擁有 datasource 是實現復雜數據綁定的第一步,但該控件需要了解數據的哪些特定字段或屬性將用作顯示和值成員。display 成員將用作樹節點的標題,而 value 成員可通過節點的 value 屬性進行訪問。這些屬性都是字符串,表示字段或屬性名,可以方便地添加到控件中:
    private m_valuemember as string    private m_displaymember as string    <category("data")> _    public property valuemember() as string        get            return m_valuemember        end get        set(byval value as string)            m_valuemember = value        end set    end property    <category("data")> _    public property displaymember() as string        get            return m_displaymember        end get        set(byval value as string)            m_displaymember = value        end set    end property

在此 treeview 中,這些屬性將僅表示葉節點的 displayvalue 成員,每個分組級別的相應信息將在 addgroup 方法中指定。

使用 currencymanager 對象


在前面探討的 datasource 屬性中,創建了一個 currencymanager 類的實例,并存儲在類級別變量中。通過該對象訪問的 currencymanager 類是實現數據綁定的關鍵部分,因為它具有的屬性、方法和事件可實現以下功能:
  • 訪問數據源的基礎 ilist 對象
  • 在數據源中檢索和設置對象字段或屬性,以及
  • 使您的控件與同一窗體中的其他數據綁定控件同步。

檢索屬性/字段值


currencymanager 對象允許您通過它的 getitemproperties 方法從數據源的單個項中檢索屬性或字段值,如 displaymembervaluemember 字段的值。然后使用 propertydescriptor 對象獲取特定列表項上的特定字段或屬性的值。下面的代碼片斷顯示了這些 propertydescriptor 對象的創建方法以及如何使用 getvalue 函數獲取基礎數據源中某一項的屬性值。請注意 currencymanager 對象的 list 屬性:通過它可以訪問該控件綁定到的 ilist 實例:
dim mynewleafnode as treeleafnodedim currobject as objectcurrobject = cm.list(currentlistindex)if me.displaymember <> "" andalso me.valuemember <> "" then    ' 添加葉節點?    dim pdvalue as system.componentmodel.propertydescriptor    dim pddisplay as system.componentmodel.propertydescriptor    pdvalue = cm.getitemproperties()(me.valuemember)    pddisplay = cm.getitemproperties()(me.displaymember)    mynewleafnode = _    new treeleafnode(cstr(pddisplay.getvalue(currobject)), _          currobject, _          pdvalue.getvalue(currobject), _          currentlistindex)

getvalue 在返回對象時忽略屬性的基本數據類型,因此在使用返回值前需要對其進行轉換。

保持數據綁定控件同步


currencymanager 還有一個主要功能:除了可以訪問綁定數據源和項屬性外,它還允許使用相同的 datasource 來協調該控件和任何其他控件之間的數據綁定。該支持可用于確保多個同時綁定到同一數據源的控件停留在數據源的同一項。對于我的控件而言,我想確保在樹中選擇項時,其他所有綁定到同一數據源的控件均指向同一項(同一記錄、行、甚至數組,如果您愿意從數據庫的角度進行思考)。為此,我覆蓋了基本 treeview 中的 onafterselect 方法。在該方法(在選擇樹節點后被調用)中,我將 currencymanager 對象的 position 屬性設置為當前選定項的索引。與該 treeview 控件一起提供的示例應用程序闡釋了同步控件如何使生成數據綁定用戶界面變得更為容易。為了使確定當前選定項的列表位置更為容易,我使用了自定義 treenode 類(treeleafnodetreegroupnode),并將每個節點的列表索引存儲到創建的 position 屬性中:
protected overrides sub onafterselect _ (byval e as system.windows.forms.treevieweventargs)    dim tln as treeleafnode    if typeof e.node is treegroupnode then        tln = findfirstleafnode(e.node)        dim groupargs as new grouptreevieweventargs(e)        raiseevent aftergroupselect(groupargs)    elseif typeof e.node is treeleafnode then        dim leafargs as new leaftreevieweventargs(e)        raiseevent afterleafselect(leafargs)        tln = ctype(e.node, treeleafnode)    end if    if not tln is nothing then        if cm.position <> tln.position then            cm.position = tln.position        end if    end if    mybase.onafterselect(e)end sub

在前面的代碼片段中,您可能注意到了一個稱為 findfirstleafnode 的函數,在此我想對其加以簡要介紹。在我的 treeview 中,只有葉節點(分層結構中的最終節點)才與 datasource 中的項相對應,其他所有節點只用于創建分組結構。如果我要創建一個性能優良的數據綁定控件,便始終需要選擇一個與 datasource 相對應的項,因此每當選擇組節點時,我就會找到該組下的第一個葉節點,就好象該節點是當前的選定內容。您可以檢查該示例的運行情況,但現在您大可放心地使用它。
private function findfirstleafnode(byval currnode as treenode) _        as treeleafnode    if typeof currnode is treeleafnode then        return ctype(currnode, treeleafnode)    else        if currnode.nodes.count > 0 then            return findfirstleafnode(currnode.nodes(0))        else            return nothing        end if    end ifend function

設置 currencymanager 對象的 position 屬性可使其他控件與當前選定項同步,但是當其他控件的位置發生變化時,currencymanager 也產生事件,以便相應地更改選定項。要成為一個優秀的數據綁定組件,所選內容應隨著數據源位置的更改而移動,修改某一項的數據時,顯示應隨之更新。currencymanager 引發的事件共有三個:currentchangeditemchangedpositionchanged。最后一個事件相當簡單;currencymanager 的用途之一是為數據源維護當前位置指示器,以便多個綁定控件均可以顯示同一記錄或列表項,只要該位置更改,此事件便會引發。其他兩個事件有時會相互重疊,因而區別不太明顯。以下分別介紹如何在自定義控件中使用這些事件:positionchanged 是一個比較簡單的事件,此處不再贅述;當您要在復雜數據綁定控件(如 tree)中調整當前選定項時,請使用該事件。只要修改數據源中的項,itemchanged 事件就會引發,而 currentchanged 只有在當前項被修改時才引發。
在我的 treeview 中,我發現每當我選擇一個新項時,所有三個事件均會引發,因此我決定通過更改當前選定項來處理 positionchanged 事件,而對另外兩項不進行任何處理。.net framework 文檔(英文)建議將數據源強制轉換為 ibindinglist(如果數據源支持 ibindinglist 的話)并改用 listchanged 事件,但我未實現此功能。
private sub cm_positionchanged(byval sender as object, _    byval e as system.eventargs) handles cm.positionchanged    dim tln as treeleafnode    if typeof me.selectednode is treeleafnode then        tln = ctype(me.selectednode, treeleafnode)    else        tln = findfirstleafnode(me.selectednode)    end if    if tln.position <> cm.position then        me.selectednode = findnodebyposition(cm.position)    end ifend subprivate overloads function findnodebyposition(byval index as integer) _        as treenode    return findnodebyposition(index, me.nodes)end functionprivate overloads function findnodebyposition(byval index as integer, _    byval nodestosearch as treenodecollection) as treenode    dim i as integer = 0    dim currnode as treenode    dim tln as treeleafnode    do while i < nodestosearch.count        currnode = nodestosearch(i)        i += 1        if typeof currnode is treeleafnode then            tln = ctype(currnode, treeleafnode)            if tln.position = index then                return currnode            end if        else            currnode = findnodebyposition(index, currnode.nodes)            if not currnode is nothing then                return currnode            end if        end if    loop    return nothingend function

將 datasource 轉變為樹


編寫完數據綁定代碼后,我可以繼續添加管理分組級別的代碼,相應地生成樹,然后添加一些自定義事件、方法和屬性。

管理組


程序員要配置組集合,就必須創建 addgroupremovegroupcleargroups 函數。每當修改組集合時,都必須重新繪制樹(以反映新配置),因此我創建了一個通用過程 groupingchanged,當情況發生變化,需要強制重建樹時,它可以由控件中的各種代碼調用:
private treegroups as new arraylist()public sub removegroup(byval group as group)    if not treegroups.contains(group) then        treegroups.remove(group)        groupingchanged()    end ifend subpublic overloads sub addgroup(byval group as group)    try        treegroups.add(group)        groupingchanged()    catch    end tryend subpublic overloads sub addgroup(byval name as string, _        byval groupby as string, _        byval displaymember as string, _        byval valuemember as string, _        byval imageindex as integer, _        byval selectedimageindex as integer)    dim mynewgroup as new group(name, groupby, _        displaymember, valuemember, _        imageindex, selectedimageindex)    me.addgroup(mynewgroup)end subpublic function getgroups() as group()    return ctype(treegroups.toarray(gettype(group)), group())end function

生成樹


樹的實際重建由一對過程來完成:buildtreeaddnodes。由于這兩個過程的代碼太長,本文并未全部列出,而是盡量概括它們的行為(當然,如果愿意您可以下載完整的代碼)。如前所述,程序員可以通過設置一系列組與該控件進行交互,然后在 buildtree 中使用這些組來確定如何設置樹節點。buildtree 清除當前節點集合,然后遍歷整個數據源來處理第一級分組(本文前面的示例和圖解中提到的 publisher),為每個不同的分組值添加一個節點(使用示例中的數據,為每個 pub_id 值添加一個節點),然后調用 addnodes 來填充第一級分組下的所有節點。addnodes 遞歸調用自身以處理任意多的級數,必要時可添加組節點和葉節點。使用兩個基于 treenode 的自定義類以區別組節點和葉節點,并為兩類節點提供各自相應的屬性。

自定義 treeview 事件


每當選擇一個節點時,treeview 都會引發兩個事件:beforeselectafterselect。但在我的控件中,我想使組節點和葉節點的事件不同,于是便添加了自己的事件 beforegroupselect/aftergroupselectbeforeleafselect/afterleafselect,除基本事件外,還引發了自定義事件參數類:
public event beforegroupselect _    (byval sender as object, byval e as grouptreeviewcanceleventargs)public event aftergroupselect _    (byval sender as object, byval e as grouptreevieweventargs)public event beforeleafselect _    (byval sender as object, byval e as leaftreeviewcanceleventargs)public event afterleafselect _    (byval sender as object, byval e as leaftreevieweventargs)protected overrides sub onbeforeselect _    (byval e as system.windows.forms.treeviewcanceleventargs)    if typeof e.node is treegroupnode then        dim groupargs as new grouptreeviewcanceleventargs(e)        raiseevent beforegroupselect(cobj(me), groupargs)    elseif typeof e.node is treeleafnode then        dim leafargs as new leaftreeviewcanceleventargs(e)        raiseevent beforeleafselect(cobj(me), leafargs)    end if    mybase.onbeforeselect(e)end subprotected overrides sub onafterselect _    (byval e as system.windows.forms.treevieweventargs)    dim tln as treeleafnode    if typeof e.node is treegroupnode then        tln = findfirstleafnode(e.node)        dim groupargs as new grouptreevieweventargs(e)        raiseevent aftergroupselect(cobj(me), groupargs)    elseif typeof e.node is treeleafnode then        dim leafargs as new leaftreevieweventargs(e)        raiseevent afterleafselect(cobj(me), leafargs)        tln = ctype(e.node, treeleafnode)    end if    if not tln is nothing then        if cm.position <> tln.position then            cm.position = tln.position        end if    end if    mybase.onafterselect(e)end sub

自定義節點類(treeleafnodetreegroupnode)和自定義事件參數類均包括在可下載代碼中。

示例應用程序


要全面理解本示例控件中的所有代碼,您應該了解它在應用程序中的運行情況。包含的示例應用程序使用 pubs.mdb access 數據庫,并說明 tree 控件如何與其他數據綁定控件一起創建 windows 應用程序。本例中,尤其值得注意的主要功能包括樹與其他綁定控件的同步以及對數據源執行搜索時樹節點的自動選擇。
注意:本示例應用程序(名為“thesample”)包含在本文的下載中。


圖 4:數據綁定 treeview 的演示應用程序

小結


本文介紹的數據綁定 tree 控件并非適用于所有需要 tree 控件來顯示數據庫信息的項目,但它確實介紹了一種可針對個人目的自定義該控件的方法。請記住,您要生成的任何復雜數據綁定控件與 tree 控件的大部分代碼基本相同,您可以通過修改現有代碼來簡化以后的控件開發過程。
在下一個示例 drawing your own controls using gdi+(英文)中,您將看到在不需要使用特定基類(就象我在該控件中繼承了 treeview 控件一樣)的情況下,實現數據綁定有一個更容易的方法。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平远县| 祁阳县| 双柏县| 韩城市| 呈贡县| 永宁县| 葫芦岛市| 苏州市| 贵溪市| 新兴县| 增城市| 南宁市| 茶陵县| 澄城县| 寿光市| 申扎县| 团风县| 张北县| 龙泉市| 湖州市| 吉安县| 镇雄县| 玉龙| 正宁县| 察隅县| 凭祥市| 富阳市| 若羌县| 临西县| 连城县| 扎囊县| 通许县| 湘阴县| 湛江市| 田东县| 陆河县| 温宿县| 花莲市| 勃利县| 印江| 洛南县|