【发布时间】:2011-11-24 14:10:55
【问题描述】:
我正在尝试在 TListView 的现有列之间添加一列。因此,我在末尾添加新列并通过将其索引设置为指定值来移动它。这有效,直到添加另一个新列。
我做了什么: 在最后一个位置添加列 (Columns.Add) 并在最后一个位置添加子项 (Subitems.Add)。之后,我通过将列的索引设置到正确的位置来移动列。 只要它只是添加一列,它就可以正常工作。添加第二个新列时,子项会搞砸。第一列的新子项移动到最后一个位置,例如像这样:
0 | 1 | new A | new B | 3
Caption | old sub 1 | old sub 3 | new Sub B | new sub A
如果有人能帮忙,我会很高兴的!
例如,是否有一个命令或消息我可以发送到 ListView 以便它刷新或保存它的列 --> 添加第一个新列后我可以使用子项映射,它是子项,所以我可以处理第二个新列的方式与第一列相同。
或者这只是 TListViews 列的错误-->子项处理或 TListColumns...?
vcl 表单应用程序的示例代码(分配 Form1.OnCreate 事件):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
listview: TListView;
initButton: TButton;
addColumn: TButton;
editColumn: TEdit;
subItemCount: Integer;
procedure OnInitClick(Sender: TObject);
procedure OnAddClick(Sender: TObject);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
listview := TListView.Create(self);
with listview do
begin
Left := 8;
Top := 8;
Width := self.Width - 30;
Height := self.Height - 100;
Anchors := [akLeft, akTop, akRight, akBottom];
TabOrder := 0;
ViewStyle := vsReport;
Parent := self;
end;
initButton := TButton.Create(self);
with initButton do
begin
left := 8;
top := listview.Top + listview.Height + 20;
Width := 75;
Height := 25;
TabOrder := 1;
Caption := 'init';
OnClick := OnInitClick;
Parent := self;
end;
editColumn := TEdit.Create(self);
with editColumn do
begin
left := initButton.Left + initButton.Width + 30;
top := listview.Top + listview.Height + 20;
Width := 120;
Height := 25;
TabOrder := 2;
Parent := self;
Caption := '';
end;
addColumn := TButton.Create(self);
with addColumn do
begin
left := editColumn.Left + editColumn.Width + 10;
top := listview.Top + listview.Height + 20;
Width := 75;
Height := 25;
TabOrder := 1;
Enabled := true;
Caption := 'add';
OnClick := OnAddClick;
Parent := self;
end;
end;
procedure TForm1.OnInitClick(Sender: TObject);
var col: TListColumn;
i, j: integer;
item: TListItem;
begin
listview.Items.Clear;
listview.Columns.Clear;
// add items
for I := 0 to 2 do
begin
col := ListView.Columns.Add;
col.Caption := 'column ' + IntToStr(i);
col.Width := 80;
end;
// add columns
for I := 0 to 3 do
begin
item := ListView.Items.Add;
item.Caption := 'ItemCaption';
// add subitems for each column
for j := 0 to 1 do
begin
item.SubItems.Add('subitem ' + IntToStr(j+1));
end;
end;
subItemCount := 5;
end;
procedure TForm1.OnAddClick(Sender: TObject);
var number: integer;
col: TListColumn;
i: Integer;
ascii: char;
begin
listview.Columns.BeginUpdate;
number := StrToInt(editColumn.Text);
ascii := Chr(65 + number);
// create the new column
col := TListColumn(ListView.Columns.add());
col.Width := 80;
col.Caption := ascii;
// add the new subitems
for I := 0 to ListView.Items.Count-1 do
begin
ListView.Items[i].SubItems.Add('subitem ' + ascii);
end;
// move it to the designated position
col.Index := number;
listview.Columns.EndUpdate;
Inc(subItemCount);
end;
end.
谢谢!
编辑:Sertac Akyuz 建议的修复工作正常,但我不能使用它,因为更改 Delphi 源代码对我的项目没有解决方案。已报告错误。
编辑:删除了第一个帖子中无意包含的第二个问题并打开了新问题(请参阅链接问题和问题修订)。
更新:reported bug 现在已关闭,与 Delphi XE2 Update 4 一样已修复。
【问题讨论】:
-
我猜某处缺少刷新/更新。虽然不确定它是什么。也就是说,这听起来像是虚拟模式列表视图会大放异彩的另一种情况。
-
但它们仅适用于 .Net,不是吗?我在等效的 C#.Net 项目中遇到了同样的问题,也许可以在那里使用它。
-
没有。 Windows 列表视图支持虚拟模式,Delphi 很好地封装了它。如果您在运行时操作列,那绝对是要走的路。这里的其他人都会将您指向虚拟树视图,但我自己喜欢本机控件。
-
好的,谢谢。 i
ll have a look at this but i don't think i can use it because the project is quite large and changing one of its 核心组件可能不是最好的主意:) -
查看了 VCL 代码,似乎在更新列索引的某处,VCL 的数据与涉及子项的 Windows 列表视图数据不同步。使用 Begin/EndUpdate 会产生效果,不幸的是到目前为止还不是想要的效果。您最好的选择可能确实是按照@David 的建议将 ListView 置于虚拟模式。这样,您的应用程序始终会被要求在每个单元格中显示它需要显示的数据,并且 vcl 或窗口中没有隐藏的“副本”。
标签: delphi dynamic tlistview subitem