Delphi: Shift-Up and Shift-Down in the Listview

后端 未结 2 568
逝去的感伤
逝去的感伤 2021-01-14 01:43

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

相关标签:
2条回答
  • 2021-01-14 02:28

    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;
    
    0 讨论(0)
  • 2021-01-14 02:35

    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.

    0 讨论(0)
提交回复
热议问题