树形视图控件 (STreeView)¶
树形视图是一个高性能的 MVC 模式控件,用于展示具有层级结构的数据。它支持展开/折叠操作,支持节点选择,并且可以通过自定义模板来实现复杂的节点显示。
基本信息¶
- 类名:
STreeView - 控件标签:
treeview - 基类:
SPanel(TPanelProxy<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句柄寻址节点,而非整型position;STreeAdapterBase已封装InsertItem/DeleteItem/GetItemData/SetItemExpanded/ExpandItem等常用操作,STVI_ROOT/STVI_LAST作为根/末尾位置常量。