GacUI的所有列表控件都支持虛擬模式。虛擬模式是一種不需要為每一個(gè)列表項(xiàng)分配內(nèi)存的一種顯示方法。在開始的時(shí)候,需要高速列表一共有多少個(gè)列表項(xiàng)。之后,列表控件在渲染的時(shí)候,會(huì)跟數(shù)據(jù)源要求獲取某一個(gè)下標(biāo)所包含的數(shù)據(jù),并且在這個(gè)數(shù)據(jù)一直處于屏幕上的時(shí)候,只會(huì)跟數(shù)據(jù)源獲取一次。完整的代碼可以在
http://www.gaclib.net/Demos/Controls.ListBox.VirtualMode/Demo.html看到。先上圖:

先看創(chuàng)建界面的代碼。一般來說,所有可以隨著窗口的變化自動(dòng)排版的控件組織方法,都是使用一個(gè)或多個(gè)GuiTableComposition來實(shí)現(xiàn)的。
class VirtualModeWindow : public GuiWindow
{
private:
GuiVirtualTextList* listBox;
GuiButton* buttonIncrease;
GuiButton* buttonDecrease;
DataSource* dataSource;
void buttonIncrease_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
{
dataSource->SetCount(dataSource->Count()+100000);
}
void buttonDecrease_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
{
dataSource->SetCount(dataSource->Count()-100000);
}
public:
VirtualModeWindow()
:GuiWindow(GetCurrentTheme()->CreateWindowStyle())
{
this->SetText(L"Controls.ListBox.VirtualMode");
GuiTableComposition* table=new GuiTableComposition;
table->SetRowsAndColumns(3, 2);
table->SetCellPadding(3);
table->SetAlignmentToParent(Margin(0, 0, 0, 0));
table->SetRowOption(0, GuiCellOption::MinSizeOption());
table->SetRowOption(1, GuiCellOption::MinSizeOption());
table->SetRowOption(2, GuiCellOption::PercentageOption(1.0));
table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0));
table->SetColumnOption(1, GuiCellOption::MinSizeOption());
this->GetContainerComposition()->AddChild(table);
{
GuiCellComposition* cell=new GuiCellComposition;
table->AddChild(cell);
cell->SetSite(0, 0, 3, 1);
dataSource=new DataSource;
listBox=new GuiVirtualTextList(GetCurrentTheme()->CreateTextListStyle(), GetCurrentTheme()->CreateTextListItemStyle(), dataSource);
listBox->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0));
listBox->SetHorizontalAlwaysVisible(false);
cell->AddChild(listBox->GetBoundsComposition());
}
{
GuiCellComposition* cell=new GuiCellComposition;
table->AddChild(cell);
cell->SetSite(0, 1, 1, 1);
buttonIncrease=g::NewButton();
buttonIncrease->SetText(L"Increase 100000 Items");
buttonIncrease->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0));
buttonIncrease->Clicked.AttachMethod(this, &VirtualModeWindow::buttonIncrease_Clicked);
cell->AddChild(buttonIncrease->GetBoundsComposition());
}
{
GuiCellComposition* cell=new GuiCellComposition;
table->AddChild(cell);
cell->SetSite(1, 1, 1, 1);
buttonDecrease=g::NewButton();
buttonDecrease->SetText(L"Decrease 100000 Items");
buttonDecrease->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0));
buttonDecrease->Clicked.AttachMethod(this, &VirtualModeWindow::buttonDecrease_Clicked);
cell->AddChild(buttonDecrease->GetBoundsComposition());
}
// set the preferred minimum client size
this->GetBoundsComposition()->SetPreferredMinSize(Size(480, 480));
// call this to calculate the size immediately if any indirect content in the table changes
// so that the window can calcaulte its correct size before calling the MoveToScreenCenter()
this->ForceCalculateSizeImmediately();
// move to the screen center
this->MoveToScreenCenter();
}
};
GuiVirtualTextList就是只有虛擬模式的GuiTextList。事實(shí)上GuiVirtualTextList是GuiTextList的基類,而GuiTextList.GetItems()返回的對(duì)象也是一個(gè)數(shù)據(jù)源。因此非虛擬模式其實(shí)也是通過虛擬模式來實(shí)現(xiàn)的。在數(shù)據(jù)比較少的時(shí)候,非虛擬模式操作起來十分的簡單,而在數(shù)據(jù)比較多的時(shí)候,虛擬模式可以帶來很好的性能。上面的代碼創(chuàng)建了一個(gè)DataSource類來做數(shù)據(jù)源,并且有一個(gè)SetCount的函數(shù)用來更改列表里面的數(shù)量的總量,然后每一個(gè)列表項(xiàng)的內(nèi)容都是Item xxx。這是怎么做到的呢?我們來看數(shù)據(jù)源的代碼:
class DataSource : public list::ItemProviderBase, private list::TextItemStyleProvider::ITextItemView
{
protected:
int count;
public:
DataSource()
:count(100000)
{
}
void SetCount(int newCount)
{
if(0<=newCount)
{
int oldCount=count;
count=newCount;
// this->InvokeOnItemModified(affected-items-start, affected-items-count, new-items-count);
// this function notifies the list control to update it's content and scroll bars
if(oldCount<newCount)
{
// insert
this->InvokeOnItemModified(oldCount, 0, newCount-oldCount);
}
else if(oldCount>newCount)
{
// delete
this->InvokeOnItemModified(newCount, oldCount-newCount, 0);
}
}
}
// GuiListControl::IItemProvider
int Count()
{
return count;
}
IDescriptable* RequestView(const WString& identifier)
{
if(identifier==list::TextItemStyleProvider::ITextItemView::Identifier)
{
return this;
}
else if(identifier==GuiListControl::IItemPrimaryTextView::Identifier)
{
return this;
}
else
{
return 0;
}
}
void ReleaseView(IDescriptable* view)
{
}
// list::TextItemStyleProvider::ITextItemView
WString GetText(int itemIndex)
{
return L"Item "+itow(itemIndex+1);
}
bool GetChecked(int itemIndex)
{
// DataSource don't support check state
return false;
}
void SetCheckedSilently(int itemIndex, bool value)
{
// DataSource don't support check state
}
// GuiListControl::IItemPrimaryTextView
WString GetPrimaryTextViewText(int itemIndex)
{
return GetText(itemIndex+1);
}
bool ContainsPrimaryText(int itemIndex)
{
return true;
}
};
對(duì)于GuiVirtualTextList來說,只需要實(shí)現(xiàn)vl::presentation::controls::list::TextItemStyleProvider::ITextItemView就可以了。GacUIIncludes.h里面已經(jīng)有了using namespace vl::presentation::controls,所以在這里只需要從list::開始寫。list::TextItemStyleProvider::ITextItemView還要求實(shí)現(xiàn)GuiListControl::IItemPrimaryTextView。在目前的GacUI里面,IItemPrimaryTextView是專門為下拉框準(zhǔn)備的。因?yàn)橄吕蛟试S接受任何一種列表對(duì)象當(dāng)做下拉內(nèi)容,所以GacUI的列表數(shù)據(jù)源默認(rèn)都要求實(shí)現(xiàn)IItemPrimaryTextView。
實(shí)現(xiàn)數(shù)據(jù)源的時(shí)候,其實(shí)并不要求數(shù)據(jù)源類繼承自ITextItemView和IItemPrimaryTextView。因?yàn)镚acUI都是通過RequestView來獲取一個(gè)View的接口指針的,代碼如上。實(shí)現(xiàn)這兩個(gè)View也很簡單,在這里就不贅述了。
GuiTextList就介紹到這里了,接下來的幾個(gè)Demo都將是關(guān)于ListView的。下一個(gè)Demo是ListView山寨Windows 7的資源管理器界面,可以在
http://www.gaclib.net/Demos/Controls.ListView.ViewSwitching/Demo.html看到。具體內(nèi)容將在下一篇博客中闡述。
posted on 2012-05-30 07:19
陳梓瀚(vczh) 閱讀(2482)
評(píng)論(1) 編輯 收藏 引用 所屬分類:
GacUI