在"平铺"视图中插入TListView的项目始终显示在列表的底部



我有一个用C++Builder XE6编写的VCL表单应用程序,它在Tile视图中包含一个TListView

由于TListViewVCL组件没有Tile视图选项,我在表单设计器中使用TListViewViewStyle=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=trueGroupView=falseRowSelect=trueShowWorkAreas=falseSortType=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);
}

最新更新