Skip to content

树形视图控件 (STreeView)

Warning

The current page still doesn't have a translation for this language.

You can read it through google translate.

树形视图是一个高性能的 MVC 模式控件,用于展示具有层级结构的数据。它支持展开/折叠操作,支持节点选择,并且可以通过自定义模板来实现复杂的节点显示。

基本信息

  • 类名STreeView
  • 控件标签treeview
  • 基类SPanelTPanelProxy<ITreeView> + SHostProxy);不是 SScrollView
  • 功能:提供树形结构数据的展示和交互

重要纠正:旧文档列出的 itemHeight / toggleSkin / checkSkin / enableCheck / multiSelect / lines / rootToggle 以及所有 color*colorText / colorSelText / colorItemBkgnd / colorSelBkgnd / lineColor)属性在 STreeView 源码中均不存在STreeView 没有勾选框、没有 toggle 皮肤属性、没有 itemHeight 独立属性(项高度由模板/项定位器决定)。多选属性名为 multiSel(不是 multiSelect)。hasLines默认值在源码中是 false(旧文档写成 1)。下为对照源码后的正确属性表。

属性说明

STreeView::SOUI_ATTRS_BEGIN 中声明的属性:

自身属性

属性名 类型 默认值 是否重绘 说明
indent layoutsize 16(px) 子节点相对父节点的缩进宽度,经 OnAttrIndent 解析并同步给项定位器 STreeViewItemLocator(其默认缩进为 16)
wantTab int 0 是否响应 Tab 键在节点间切换焦点
hasLines bool false 是否绘制节点之间的连接线
multiSel bool false 是否允许多选(与 SViewBase 同名属性语义一致,此处为本类自身声明)
lineSkin skin 系统皮肤 SKIN_SYS_TREE_LINES 连接线皮肤(仅当 hasLines="1" 时绘制)

说明:构造函数成员初始化为 m_bHasLines(FALSE)m_bWantTab(FALSE)m_bMultiSel(FALSE)m_pLineSkin(GETBUILTINSKIN(SKIN_SYS_TREE_LINES))。节点展开/折叠按钮、复选框等属于项模板template 内子控件)的内容,不是 treeview 的 XML 属性。

使用示例

treeview 的数据由 ITvAdapter 提供,SOUI 给出便捷基类 STreeAdapterBase<T>helper/SAdapterBase.h),内部用 CSTree 管理层级关系,你只需 InsertItem() 增节点、GetItemData(hItem) 取数据。模板同样支持 item_group/item_data 多模板。完整可运行示例见 demos/wxDemo/CTvContactAdapter.h

1. XML 模板

<treeview pos="0,0,-0,-0" name="tv_contact" indent="0"
          sbSkin="skin_scrollbar" sbwid="8">
    <template>
        <item_group focusable="0" size="240,30" layout="vbox">
            <text name="name" align="bottom" font="face:微软雅黑,size:12"/>
        </item_group>
        <item_data size="240,60" layout="hbox" gravity="center"
                   colorHover="#dddbda" colorSelected="#c9c7c6">
            <img name="face" skin="skin_default_personal32"/>
            <text name="name" font="face:微软雅黑,size:16"/>
        </item_data>
    </template>
</treeview>

2. 实现适配器(C++)

#include <helper/SAdapterBase.h>
#include <control/STreeView.h>

struct Contact
{
    SStringT strName;
    SStringT strImg;
    bool     bGroup;
};

class CContactTreeAdapter : public STreeAdapterBase<Contact>
{
public:
    void Build()
    {
        Contact g; g.bGroup = true; g.strName = _T("好友");
        HSTREEITEM hGroup = InsertItem(g);
        SetItemExpanded(hGroup, TRUE);

        Contact c; c.bGroup = false; c.strName = _T("张三");
        c.strImg = _T("skin_default_personal32");
        InsertItem(c, hGroup);
    }

protected:
    virtual int WINAPI getViewType(HSTREEITEM hItem) const override
    {
        return GetItemData(hItem).bGroup ? 0 : 1;
    }
    virtual int WINAPI getViewTypeCount() const override { return 2; }

    virtual void WINAPI getView(HSTREEITEM hItem, SItemPanel *pItem,
                                SXmlNode xmlTemplate) override
    {
        if (pItem->GetChildrenCount() == 0)
        {
            SXmlNode sub = (getViewType(hItem) == 0)
                             ? xmlTemplate.child(L"item_group")
                             : xmlTemplate.child(L"item_data");
            pItem->InitFromXml(&sub);
        }
        const Contact &data = GetItemData(hItem);
        pItem->FindChildByName2<SStatic>(L"name")->SetWindowText(data.strName);
        if (!data.bGroup)
            pItem->FindChildByName(L"face")->SetAttribute(L"skin", S_CT2W(data.strImg));
    }
};

3. 绑定与交互

void InitTree(STreeView *pTree)
{
    CContactTreeAdapter *pAdapter = new CContactTreeAdapter;
    pAdapter->Build();
    pTree->SetAdapter(pAdapter);
    pAdapter->Release();

    pTree->SetMultiSel(TRUE);
    // 展开/折叠在适配器内通过 ExpandItem(hItem, TVC_TOGGLE) 控制
}

与列表类不同,树适配器以 HSTREEITEM 句柄寻址节点,而非整型 positionSTreeAdapterBase 已封装 InsertItem/DeleteItem/GetItemData/SetItemExpanded/ExpandItem 等常用操作,STVI_ROOT/STVI_LAST 作为根/末尾位置常量。

相关主题