致电UpdateItems排列列后的方法。例如。:
..
col.Index := number;
listview.UpdateItems(0, MAXINT);
..
Update:
在我的测试中,在某些情况下我似乎仍然需要上述调用。但真正的问题是“Delphi 列表视图控件中存在错误”.
用一个简单的项目复制问题:
- Place a
TListView
VCL 窗体上的控件,设置其ViewStyle
到“vsReport”并设置FullDrag
到“真实”。
- 将以下代码放入
OnCreate
表单的处理程序:ListView1.Columns.Add.Caption := 'col 1';
ListView1.Columns.Add.Caption := 'col 2';
ListView1.Columns.Add.Caption := 'col 3';
ListView1.AddItem('cell 1', nil);
ListView1.Items[0].SubItems.Add('cell 2');
ListView1.Items[0].SubItems.Add('cell 3');
- Place a
TButton
在表单上,并将以下代码放入其OnClick
处理程序:ListView1.Columns.Add.Caption := 'col 4';
- Run the project and drag the column header of 'col 3' to in-between 'col 1' and 'col 2'. The below picture is what you'll see at this moment (everything is fine):
- Click the button to add a new column, now the list view becomes:
Notice that 'cell 2' has reclaimed its original position.
Bug:
a 的列TListView
(TListColumn
)将其订购信息保存在其FOrderTag
场地。每当您更改列的顺序(通过设置Index
属性或通过拖动标题),这FOrderTag
得到相应更新。
现在,当您向TListColumns
集合,集合首先添加新的TListColumn
然后调用UpdateCols
方法。下面是代码UpdateCols
的方法TListColumns
在 D2007 VCL 中:
procedure TListColumns.UpdateCols;
var
I: Integer;
LVColumn: TLVColumn;
begin
if not Owner.HandleAllocated then Exit;
BeginUpdate;
try
for I := Count - 1 downto 0 do
ListView_DeleteColumn(Owner.Handle, I);
for I := 0 to Count - 1 do
begin
with LVColumn do
begin
mask := LVCF_FMT or LVCF_WIDTH;
fmt := LVCFMT_LEFT;
cx := Items[I].FWidth;
end;
ListView_InsertColumn(Owner.Handle, I, LVColumn);
Items[I].FOrderTag := I;
end;
Owner.UpdateColumns;
finally
EndUpdate;
end;
end;
上面的代码从底层 API 列表视图控件中删除所有列,然后重新插入它们。请注意代码如何分配每个插入列的FOrderTag
索引计数器:
Items[I].FOrderTag := I;
这是该时间点从左到右的列顺序。如果每当列的排序与创建时不同时调用该方法,则该排序将丢失。由于物品不会相应地改变它们的位置,所以一切都会变得混乱。
Fix:
根据我的测试,以下对该方法的修改似乎有效,您需要进行更多测试(显然这个修复并没有涵盖所有可能的情况,请参阅下面的“torno”评论以了解详细信息):
procedure TListColumns.UpdateCols;
var
I: Integer;
LVColumn: TLVColumn;
ColumnOrder: array of Integer;
begin
if not Owner.HandleAllocated then Exit;
BeginUpdate;
try
SetLength(ColumnOrder, Count);
for I := Count - 1 downto 0 do begin
ColumnOrder[I] := Items[I].FOrderTag;
ListView_DeleteColumn(Owner.Handle, I);
end;
for I := 0 to Count - 1 do
begin
with LVColumn do
begin
mask := LVCF_FMT or LVCF_WIDTH;
fmt := LVCFMT_LEFT;
cx := Items[I].FWidth;
end;
ListView_InsertColumn(Owner.Handle, I, LVColumn);
end;
ListView_SetColumnOrderArray(Owner.Handle, Count, PInteger(ColumnOrder));
Owner.UpdateColumns;
finally
EndUpdate;
end;
end;
如果您不使用包,您可以将“comctrls.pas”的修改副本放入您的项目文件夹中。否则,您可能会寻求运行时代码修补,或提交错误报告并等待修复。