Delphi:列表视图中的 Shift-Up 和 Shift-Down

发布于 2024-10-22 06:00:21 字数 34 浏览 1 评论 0原文

Listview 控件中是否有可以上下移动项目的功能?

Is there a feature in the Listview control to shift items up and down?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

煞人兵器 2024-10-29 06:00:21

由于没有太多使用 TListView (我主要使用数据库网格),我将你的问题视为学习一些东西的机会。下面的代码是结果,它比大卫的答案更直观。它有一些限制:它只会移动第一个选定的项目,并且在移动项目时,移动后 vsIcon 和 vsSmallIcon 的显示很奇怪。

procedure TForm1.btnDownClick(Sender: TObject);
var
  Index: integer;
  temp : TListItem;
begin
  // use a button that cannot get focus, such as TSpeedButton
  if ListView1.Focused then
    if ListView1.SelCount>0 then
    begin
      Index := ListView1.Selected.Index;
      if Index<ListView1.Items.Count then
      begin
        temp := ListView1.Items.Insert(Index+2);
        temp.Assign(ListView1.Items.Item[Index]);
        ListView1.Items.Delete(Index);
        // fix display so moved item is selected/focused
        ListView1.Selected := temp;
        ListView1.ItemFocused := temp;
      end;
    end;
end;

procedure TForm1.btnUpClick(Sender: TObject);
var
  Index: integer;
  temp : TListItem;
begin
  // use a button that cannot get focus, such as TSpeedButton
  if ListView1.Focused then
    if ListView1.SelCount>0 then
    begin
      Index := ListView1.Selected.Index;
      if Index>0 then
      begin
        temp := ListView1.Items.Insert(Index-1);
        temp.Assign(ListView1.Items.Item[Index+1]);
        ListView1.Items.Delete(Index+1);
        // fix display so moved item is selected/focused
        ListView1.Selected := temp;
        ListView1.ItemFocused := temp;
      end;
    end;
end;

Not having worked with TListView very much (I mostly use database grids), I took your question as a chance to learn something. The following code is the result, it is more visually oriented that David's answer. It has some limitations: it will only move the first selected item, and while it moves the item, the display for vsIcon and vsSmallIcon is strange after the move.

procedure TForm1.btnDownClick(Sender: TObject);
var
  Index: integer;
  temp : TListItem;
begin
  // use a button that cannot get focus, such as TSpeedButton
  if ListView1.Focused then
    if ListView1.SelCount>0 then
    begin
      Index := ListView1.Selected.Index;
      if Index<ListView1.Items.Count then
      begin
        temp := ListView1.Items.Insert(Index+2);
        temp.Assign(ListView1.Items.Item[Index]);
        ListView1.Items.Delete(Index);
        // fix display so moved item is selected/focused
        ListView1.Selected := temp;
        ListView1.ItemFocused := temp;
      end;
    end;
end;

procedure TForm1.btnUpClick(Sender: TObject);
var
  Index: integer;
  temp : TListItem;
begin
  // use a button that cannot get focus, such as TSpeedButton
  if ListView1.Focused then
    if ListView1.SelCount>0 then
    begin
      Index := ListView1.Selected.Index;
      if Index>0 then
      begin
        temp := ListView1.Items.Insert(Index-1);
        temp.Assign(ListView1.Items.Item[Index+1]);
        ListView1.Items.Delete(Index+1);
        // fix display so moved item is selected/focused
        ListView1.Selected := temp;
        ListView1.ItemFocused := temp;
      end;
    end;
end;
飘过的浮云 2024-10-29 06:00:21

您有两个选择:

  • 删除它们,然后将它们重新插入到新位置。
  • 使用虚拟列表视图并将它们移动到数据结构中。

我执行第一个选项的例程如下:

procedure TBatchTaskList.MoveTasks(const Source: array of TListItem; Target: TListItem);
var
  i, InsertIndex: Integer;
begin
  Assert(IsMainThread);
  BeginUpdate;
  Try
    //work out where to move them
    if Assigned(Target) then begin
      InsertIndex := FListItems.IndexOf(Target);
    end else begin
      InsertIndex := FListItems.Count;
    end;

    //create new items for each moved task
    for i := 0 to high(Source) do begin
      SetListItemValues(
        FListItems.Insert(InsertIndex+i),
        TBatchTask(Source[i].Data)
      );
      Source[i].Data := nil;//handover ownership to the new item
    end;

    //set selection and focus item to give feedback about the move
    for i := 0 to high(Source) do begin
      FListItems[InsertIndex+i].Selected := Source[i].Selected;
    end;
    FBatchList.ItemFocused := FListItems[InsertIndex];

    //delete the duplicate source tasks
    for i := 0 to high(Source) do begin
      Source[i].Delete;
    end;
  Finally
    EndUpdate;
  End;
end;

SetListItemValues 方法用于填充列表视图的列。

这是虚拟控件为何如此出色的完美示例。

You have two options:

  • Delete them and then re-insert them at the new location.
  • Use a virtual list view and move them in your data structure.

My routine for doing the first of these options is like this:

procedure TBatchTaskList.MoveTasks(const Source: array of TListItem; Target: TListItem);
var
  i, InsertIndex: Integer;
begin
  Assert(IsMainThread);
  BeginUpdate;
  Try
    //work out where to move them
    if Assigned(Target) then begin
      InsertIndex := FListItems.IndexOf(Target);
    end else begin
      InsertIndex := FListItems.Count;
    end;

    //create new items for each moved task
    for i := 0 to high(Source) do begin
      SetListItemValues(
        FListItems.Insert(InsertIndex+i),
        TBatchTask(Source[i].Data)
      );
      Source[i].Data := nil;//handover ownership to the new item
    end;

    //set selection and focus item to give feedback about the move
    for i := 0 to high(Source) do begin
      FListItems[InsertIndex+i].Selected := Source[i].Selected;
    end;
    FBatchList.ItemFocused := FListItems[InsertIndex];

    //delete the duplicate source tasks
    for i := 0 to high(Source) do begin
      Source[i].Delete;
    end;
  Finally
    EndUpdate;
  End;
end;

The method SetListItemValues is used to populate the columns of the list view.

This is a perfect example of why virtual controls are so great.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文