我有一个用C++Builder XE6编写的VCL表单应用程序,它在Tile视图中包含一个TListView
。
由于TListView
VCL组件没有Tile视图选项,我在表单设计器中使用TListView
和ViewStyle=vsReport
,并在代码中将其切换到Tile视图
void __fastcall TForm1::FormShow (TObject *Sender)
{
TLVTileViewInfo tvi = {};
tvi.cbSize = sizeof(tvi);
tvi.dwMask = LVTVIM_COLUMNS;
tvi.cLines = ListView1->Columns->Count - 1;
ListView_SetTileViewInfo(ListView1->Handle, &tvi);
ListView_SetView(ListView1->Handle, LV_VIEW_TILE);
}
TListView
还具有Checkboxes=true
、GroupView=false
、RowSelect=true
、ShowWorkAreas=false
和SortType=stNone
。
TListView
具有以下OnInsert
事件处理程序:
void __fastcall TForm1::ListView1Insert (TObject *Sender, TListItem *Item)
{
TLVTileInfo ti = {};
Item->Caption = " "; // ComCtl32.dll throws an access violation exception when caption is empty.
ti.cbSize = sizeof(ti);
ti.iItem = Item->Index;
ti.cColumns = ListView1->Columns->Count - 1;
ti.puColumns = new unsigned[ti.cColumns];
ti.piColFmt = new int[ti.cColumns];
try
{
for (unsigned i = 0; i < ti.cColumns; i++)
{
ti.puColumns[i] = 1 + i;
ti.piColFmt [i] = LVCFMT_LEFT;
}
ListView_SetTileInfo(ListView1->Handle, &ti);
}
__finally
{
delete[] ti.puColumns;
delete[] ti.piColFmt;
}
}
我在TListView
中插入一个项目,例如在顶部:
TListItem* Item = ListView1->Items->Insert(0);
项目插入在列表的顶部(插入后Item->Index
为0(,但显示在屏幕上列表视图的底部。
当我删除一个项目时,列表视图会显示一个空白的空间,该空间是磁贴曾经所在的位置。我在删除后用以下代码修复了这个问题:
ListView_Arrange(ListView1->Handle, LVA_DEFAULT);
这将从列表视图中删除空白。
不幸的是,当在插入项目后调用时,这没有任何效果。新插入的项目仍显示在列表视图的底部。
如果我在"报告"视图的列表视图中插入一个项目,则所有操作都会按预期进行。只是在平铺视图中没有。
如何使列表视图在平铺视图中按正确顺序(即项目的Index
属性的升序(显示项目?
更新
事实证明,将视图切换到任何其他类型并返回到LV_VIEW_TILE
会使列表视图按正确的顺序排列项目。
这可以在插入新项目后完成:
void __fastcall TForm1::Button1Click (TObject *Sender)
{
ListView1->Items->BeginUpdate(); // Disable repainting list view.
try
{
TListItem* Item = ListView1->Items->Insert(0);
Item->Caption = "New item";
ListView_SetView(ListView1->Handle, LV_VIEW_LIST); // Can be any LV_VIEW_... value other than LV_VIEW_TILE.
ListView_SetView(ListView1->Handle, LV_VIEW_TILE);
}
__finally
{
ListView1->Items->EndUpdate(); // Enable repainting list view.
}
}
尝试将此代码作为变通方案,执行您想要的操作,您甚至不会注意到从列表视图切换到平铺视图。
void __fastcall TForm3::Button1Click(TObject *Sender)
{
ViewList(); // set ViewStyle to LV_VIEW_LIST
TListItem *item;
item = ListView1->Items->Insert(2); // insert it @ item index 2
// or ListView1->Items->Insert(ListView1->Selected->Index);
item->Caption = "Hello 1";
ViewTile(); // restore view to LV_VIEW_TILE
}
//---------------------------------------------------------------------------
void __fastcall TForm3::ViewTile()
{
//set view to Tile View
TLVTileViewInfo tvi = {};
tvi.cbSize = sizeof(tvi);
tvi.dwMask = LVTVIM_COLUMNS;
tvi.cLines = ListView1->Columns->Count - 1;
ListView_SetTileViewInfo(ListView1->Handle, &tvi);
ListView_SetView(ListView1->Handle, LV_VIEW_TILE);
}
//---------------------------------------------------------------------------
void __fastcall TForm3::ViewList()
{
// restore view to List View aka vsReport
TLVTileViewInfo tvi = {};
tvi.cbSize = sizeof(tvi);
tvi.dwMask = LVTVIM_COLUMNS;
tvi.cLines = ListView1->Columns->Count - 1;
ListView_SetTileViewInfo(ListView1->Handle, &tvi);
ListView_SetView(ListView1->Handle, LV_VIEW_LIST);
}
添加您的ListView_Arrange(ListView1->句柄,LVA_DEFAULT(;到您的弹出菜单的Delete1Click事件(您已经这样做了,但在这里为其他人显示(。
void __fastcall TForm3::Delete1Click(TObject *Sender)
{
ListView1->DeleteSelected();
ListView_Arrange(ListView1->Handle, LVA_DEFAULT);
}
在阅读了Raymond Chen的博客文章Positioned vs.non-posited listview views后,我找到了另一种插入新项目的方法,它不需要切换视图:
void __fastcall TForm1::Button1Click (TObject *Sender)
{
TPoint P;
// Get position of item to insert before (in this case: the 1st item in the list).
ListView_GetItemPosition(ListView1->Handle, 0, &P);
// Insert new item (will be positioned at the bottom of the list).
TListItem* Item = ListView1->Items->Insert(0);
Item->Caption = "New item";
// Move new item to same position as item inserted before (now the 2nd item in the list).
ListView_SetItemPosition(ListView1->Handle, Item->Index, P.X, P.Y);
// Rearrange items in the list.
ListView_Arrange(ListView1->Handle, LVA_DEFAULT);
}