跳转至

组合视图控件 (SComboView)

SOUI中的组合视图控件,结合了下拉列表和自定义视图的功能。可以在下拉框中显示自定义的视图内容,比如列表视图、树形视图等,支持灵活的数据展示和选择方式。

基本信息

  • 类名SComboView
  • 控件标签comboview
  • 基类SComboBase
  • 功能:提供下拉式自定义视图选择功能

基本属性

属性名 类型 默认值 说明
dropWidth int -1 下拉框宽度
dropHeight int - 下拉框高度

使用示例

基础组合视图

<!-- 基础组合视图 -->
<comboview pos="10,10,200,40" name="combo_basic"
           dropWidth="300" dropHeight="400">
    <liststyle>
        <template itemHeight="30">
            <text pos="5,|-15" name="txt_name"/>
            <text pos="[5,|-15" name="txt_value"
                  colorText="#666666"/>
        </template>
    </liststyle>
</comboview>

自定义样式组合视图

<!-- 自定义样式组合视图 -->
<comboview pos="10,50,300,80" name="combo_custom"
           dropWidth="400" dropHeight="500">
    <editstyle inset="5,0,5,0" 
               colorBkgnd="#FFFFFF"
               colorText="#000000"/>
    <liststyle>
        <template itemHeight="60">
            <window>
                <img pos="5,5,55,55" name="img_icon"/>
                <text pos="65,10" name="txt_title"
                      font="bold:1"/>
                <text pos="65,35" name="txt_desc"
                      colorText="#666666"/>
            </window>
        </template>
    </liststyle>
</comboview>

带搜索功能的组合视图

<!-- 带搜索功能的组合视图 -->
<comboview pos="10,100,300,130" name="combo_search"
           dropWidth="300" dropHeight="300">
    <editstyle inset="5,0,5,0" 
               colorBkgnd="#FFFFFF"
               colorText="#000000"/>
    <liststyle>
        <template itemHeight="30">
            <text pos="5,|-15" name="txt_item"/>
        </template>
    </liststyle>
</comboview>

事件处理

组合视图控件支持以下事件:

事件名 EventID 说明
EVT_CB_SELCHANGE EventCBSelChange::EventID 选择改变事件
EVT_CB_DROPDOWN EventCBDropDown::EventID 下拉框展开事件
EVT_CB_CLOSEUP EventCBCloseUp::EventID 下拉框关闭事件
// 事件处理示例
EVENT_MAP_BEGIN()
    EVENT_NAME_HANDLER(L"combo_basic", EventCBSelChange::EventID, OnCBSelChange)
    EVENT_NAME_HANDLER(L"combo_basic", EventCBDropDown::EventID, OnCBDropDown)
    EVENT_NAME_HANDLER(L"combo_basic", EventCBCloseUp::EventID, OnCBCloseUp)
EVENT_MAP_END()

void OnCBSelChange(IEvtArgs *pEvt)
{
    EventCBSelChange *pRealEvt = sobj_cast<EventCBSelChange>(pEvt);
    int nCurSel = pRealEvt->nCurSel;
    // 处理选择改变事件
}

void OnCBDropDown(IEvtArgs *pEvt)
{
    // 处理下拉框展开事件
}

void OnCBCloseUp(IEvtArgs *pEvt)
{
    // 处理下拉框关闭事件
}

代码操作

// 查找组合视图控件
SComboView *pComboView = FindChildByName2<SComboView>(L"combo_basic");

// 设置适配器
pComboView->SetAdapter(pAdapter);

// 获取当前选中项
int nCurSel = pComboView->GetCurSel();

// 设置选中项
pComboView->SetCurSel(0);

// 获取项目数量
int nCount = pComboView->GetCount();

// 设置下拉框尺寸
pComboView->SetAttribute(L"dropWidth", L"350");
pComboView->SetAttribute(L"dropHeight", L"450");

// 获取编辑框
SEdit* pEdit = pComboView->GetEditBox();

// 设置编辑框文本
pEdit->SetWindowText(L"自定义文本");

// 获取编辑框文本
SStringT strText;
pEdit->GetWindowText(strText);

实现国家选择器示例

#include <helper/SAdapterBase.h>

// 国家数据结构
struct CountryData
{
    SStringT strName;        // 国家名称
    SStringT strCode;        // 国家代码
    SStringT strFlagSkin;    // 国旗图标皮肤
    SStringT strContinent;   // 所属洲
};

// 国家选择器适配器
class CCountryAdapter : public SAdapterBase
{
protected:
    SArray<CountryData> m_countries;
    SArray<CountryData> m_filteredCountries; // 用于搜索过滤
    SStringT m_strFilter; // 搜索过滤条件

public:
    // 获取项目描述,用户选择一项后,将使用这个返回值填充comboview的edit/text部分。
    STDMETHOD_(SStringW, getItemDesc)(int position)
    {
        return SStringW().Format(L"%s (%s)", m_filteredCountries[position].strName.c_str(), m_filteredCountries[position].strCode.c_str());
    }

    // 获取项目数量,注意 WINAPI 调用约定
    virtual int WINAPI getCount()
    {
        return m_filteredCountries.GetCount();
    }

    // 获取视图,注意 WINAPI 调用约定
    virtual void WINAPI getView(int position, SItemPanel* pItem, SXmlNode xmlTemplate)
    {
        if(pItem->GetChildrenCount() == 0)
        {
            pItem->InitFromXml(&xmlTemplate);
        }

        if(position >= 0 && position < m_filteredCountries.GetCount())
        {
            const CountryData& country = m_filteredCountries[position];

            // 设置国旗
            SWindow* pFlag = pItem->FindChildByName(L"img_flag");
            if(pFlag)
            {
                pFlag->SetAttribute(L"skin", country.strFlagSkin);
            }

            // 设置国家名称
            SWindow* pName = pItem->FindChildByName(L"txt_name");
            if(pName)
            {
                pName->SetWindowText(country.strName);
            }

            // 设置国家代码
            SWindow* pCode = pItem->FindChildByName(L"txt_code");
            if(pCode)
            {
                pCode->SetWindowText(country.strCode);
            }
        }
    }

    // 添加国家
    void AddCountry(const CountryData& country)
    {
        m_countries.Add(country);
        ApplyFilter(); // 重新应用过滤器
    }

    // 设置搜索过滤条件
    void SetFilter(const SStringT& strFilter)
    {
        m_strFilter = strFilter;
        ApplyFilter();
    }

    // 应用过滤器
    void ApplyFilter()
    {
        m_filteredCountries.RemoveAll();

        if(m_strFilter.IsEmpty())
        {
            // 无过滤条件,显示所有国家
            m_filteredCountries.Copy(m_countries);
        }
        else
        {
            // 根据过滤条件筛选国家
            for(int i = 0; i < m_countries.GetCount(); i++)
            {
                const CountryData& country = m_countries[i];
                if(country.strName.Find(m_strFilter) != -1 || 
                   country.strCode.Find(m_strFilter) != -1)
                {
                    m_filteredCountries.Add(country);
                }
            }
        }

        notifyDataSetChanged();
    }

    // 获取指定位置的国家数据
    const CountryData& GetCountry(int position)
    {
        return m_filteredCountries[position];
    }
};

// 初始化国家选择器
void InitCountrySelector()
{
    SComboView* pComboView = FindChildByName2<SComboView>(L"combo_country");
    if(pComboView)
    {
        CCountryAdapter* pAdapter = new CCountryAdapter();

        // 添加一些示例国家数据
        CountryData countries[] = {
            {L"中国", L"CN", L"skin_flag_cn", L"亚洲"},
            {L"美国", L"US", L"skin_flag_us", L"北美洲"},
            {L"英国", L"UK", L"skin_flag_uk", L"欧洲"},
            {L"日本", L"JP", L"skin_flag_jp", L"亚洲"},
            {L"德国", L"DE", L"skin_flag_de", L"欧洲"},
            {L"法国", L"FR", L"skin_flag_fr", L"欧洲"},
            {L"加拿大", L"CA", L"skin_flag_ca", L"北美洲"},
            {L"澳大利亚", L"AU", L"skin_flag_au", L"大洋洲"}
        };

        for(int i = 0; i < sizeof(countries)/sizeof(countries[0]); i++)
        {
            pAdapter->AddCountry(countries[i]);
        }

        // 设置适配器
        pComboView->SetAdapter(pAdapter);
        pAdapter->Release();

        // 订阅编辑框文本变化事件以实现搜索功能
        SEdit* pEdit = pComboView->GetEditBox();
        if(pEdit)
        {
            pEdit->GetEventSet()->subscribeEvent(
                EventEditTextChanged::EventID,
                Subscriber(&OnEditTextChanged, this));
        }
    }
}

// 处理编辑框文本变化事件
bool OnEditTextChanged(EventArgs* pEvt)
{
    SEdit* pEdit = sobj_cast<SEdit>(pEvt->sender);
    if(pEdit)
    {
        SComboView* pComboView = sobj_cast<SComboView>(pEdit->GetParent());
        if(pComboView)
        {
            CCountryAdapter* pAdapter = (CCountryAdapter*)pComboView->GetAdapter();
            if(pAdapter)
            {
                SStringT strText;
                pEdit->GetWindowText(strText);
                pAdapter->SetFilter(strText); // 设置过滤条件
            }
        }
    }
    return true;
}

// 处理国家选择事件
void OnCountrySelected(int nIndex)
{
    SComboView* pComboView = FindChildByName2<SComboView>(L"combo_country");
    if(pComboView)
    {
        CCountryAdapter* pAdapter = (CCountryAdapter*)pComboView->GetAdapter();
        if(pAdapter && nIndex >= 0)
        {
            const CountryData& country = pAdapter->GetCountry(nIndex);
            // 处理国家选择,例如保存选择结果
            SaveSelectedCountry(country.strCode);
        }
    }
}

最佳实践

  1. 尺寸设置:合理设置 dropWidthdropHeight,确保下拉内容完整显示
  2. 模板设计:使用合适的模板设计项目视图,确保数据展示清晰易读
  3. 交互体验:为编辑框设置合适的样式,提供良好的用户输入体验

常见问题

Q: 下拉框显示不完整怎么办?

A: 检查 dropWidthdropHeight 是否设置合适,确保内容完整显示。

Q: 搜索功能如何实现?

A: 通过监听编辑框输入事件,动态过滤适配器中的数据。

相关控件