Skip to content

多列列表视图控件 (SMCListView)

Warning

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

You can read it through google translate.

SOUI 中的多列列表视图控件,类似于 Windows 的列表控件,支持多列数据显示,具有表头、排序、列宽调整等功能。基于虚拟化(adapter)技术实现,适用于大量数据的表格形式展示。

基本信息

  • 类名SMCListView
  • 控件标签mclistview
  • 基类SPanelTPanelProxy<IMcListView> + SViewBase);不是 SListView 的子类
  • 功能:提供多列数据表格形式展示

重要纠正:旧文档列出的 gridLines(bool)属性在源码中不存在SMCListView 没有布尔“显示网格线”开关,网格颜色由 colorGrid(color)控制;未设置 colorGrid 时不绘制网格。另外旧文档缺少 hotTrack / dividerSkin / dividerSize 等真实属性。

属性说明

SMCListView::SOUI_ATTRS_BEGIN 中声明的属性,并通过 ATTR_CHAIN_CLASS(SViewBase) 继承选择相关属性:

自身属性

属性名 类型 默认值 是否重绘 说明
headerHeight layoutsize 未设置(0) 表头高度
hotTrack int 0 是否启用热点跟踪(鼠标悬停高亮整行),0=关闭,1=开启
dividerSkin skin 表头/列之间的分割线皮肤
dividerSize layoutsize 未设置(0) 分割线尺寸
colorGrid color 0(透明) 网格线颜色;设为非透明色即绘制网格
wantTab bool false 是否响应 Tab 键(由 SViewBase 提供)
multiSel bool false 是否允许多选(由 SViewBase 提供)

说明:列定义(标题、宽度、对齐、排序)通过子节点 <header> 配置,属于 SHeaderCtrl 的属性,不在此表的 mclistview 自身属性之列。

使用示例

mclistviewlistview 的基础上增加了表头(SHeaderCtrl)。列定义既可在 XML 的 <headerStyle>/<items> 中静态声明,也可用 InsertColumn() 在代码中动态插入;数据同样由 IMcAdapter(便捷基类 SMcAdapterBase)提供。完整可运行示例见 demos/mclistview_demo/StudentSmsDlg.cpp

1. XML(静态表头 + 分组/数据两种行模板)

<mclistview pos="10,10,-10,-10" name="mclist_student"
            headerHeight="30" colorGrid="#E0E0E0">
    <headerStyle align="center" itemSwapEnable="1" sortHeader="1" itemSkin="sms.header">
        <items>
            <item width="200">昵称</item>
            <item width="215">有效期</item>
            <item width="75">忠诚度</item>
        </items>
    </headerStyle>
    <template itemHeight="26">
        <item_group colorHover="#e4f0fc" colorSelected="#e4e0ec">
            <check  name="chk_select_group" pos="0,|0" offset="0,-0.5"/>
            <toggle name="tgl_tv_expand"  pos="[6,|0" offset="0,-0.5" skin="_skin.sys.tree.toggle"/>
            <text  name="txt_group" pos="[5,|0" offset="0,-0.5" font="bold:1"/>
        </item_group>
        <item_data colorHover="#e4f0fc" colorSelected="#e4e0ec">
            <text name="txt_nick"         pos="24,|0" offset="0,-0.5">sb01</text>
            <text name="txt_time_span"    pos="10,|0" offset="0,-0.5">2015/9 - 2028/9</text>
            <text name="txt_loyal_degree" pos="-15,|0" offset="-1,-0.5">10000</text>
        </item_data>
    </template>
</mclistview>

列名在 XML 中声明;适配器通过 GetColumnName(iCol) 返回每列在模板中对应的窗口名(如 col_nick/col_time_span/col_loyal_degree),控件据此把数据填到正确的列。item_group/item_data 两种模板演示“分组头 + 可折叠数据行”。

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

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

struct Stu
{
    SStringT strNick;
    UINT     imid;
    BOOL     bChecked;
};

class CStudentAdapter : public SMcAdapterBase
{
public:
    void AddStudent(const Stu &s)
    {
        m_stu.Add(s);
        notifyDataSetChanged();
    }

protected:
    virtual int WINAPI getCount() override { return m_stu.GetCount(); }

    virtual int WINAPI getItemViewType(int position) override
    {
        return (position == 0) ? 0 : 1;
    }
    virtual int WINAPI getViewTypeCount() override { return 2; }

    virtual SStringW WINAPI GetColumnName(int iCol) const override
    {
        SStringW cols[] = {L"col_nick", L"col_time_span", L"col_loyal_degree"};
        return cols[iCol];
    }

    virtual void WINAPI getView(int position, SItemPanel *pItem, SXmlNode xmlTemplate) override
    {
        int vt = getItemViewType(position);
        if (pItem->GetChildrenCount() == 0)
        {
            SXmlNode sub = (vt == 0) ? xmlTemplate.child(L"item_group")
                                     : xmlTemplate.child(L"item_data");
            pItem->InitFromXml(&sub);
        }
        if (vt == 1)
        {
            const Stu &s = m_stu[position - 1];
            pItem->FindChildByName2<SStatic>(L"txt_nick")
                 ->SetWindowText(SStringT().Format(_T("%s(%u)"), s.strNick, s.imid));
        }
    }

private:
    SArray<Stu> m_stu;
};

3. 绑定与动态插列

void InitMcList(SMCListView *pList)
{
    CStudentAdapter *pAdapter = new CStudentAdapter;
    pAdapter->AddStudent({_T("张三"), 1001, FALSE});
    pAdapter->AddStudent({_T("李四"), 1002, FALSE});

    pList->SetAdapter(pAdapter);
    pAdapter->Release();

    // 也可在代码里动态插列(会覆盖 XML 静态表头):
    // pList->InsertColumn(0, L"昵称",   200, LVCFMT_LEFT);
    // pList->InsertColumn(1, L"有效期", 215, LVCFMT_LEFT);
    // pList->InsertColumn(2, L"忠诚度",  75, LVCFMT_RIGHT);

    pList->SetMultiSel(TRUE);
}

相关主题