【问题标题】:Delphi: Shift-Up and Shift-Down in the ListviewDelphi:列表视图中的 Shift-Up 和 Shift-Down
【发布时间】:2011-03-13 11:13:43
【问题描述】:

Listview 控件中有上下移动项目的功能吗?

【问题讨论】:

  • 按标题,Language是Delphi,按语言,OS肯定是Windows。
  • 抱歉,我通常会检查这些东西的标签。如果你把它放在标题的末尾(在括号中),它可能会被遗漏。
  • @Kermia:你忘了说你在“报告模式”下使用了控件(ViewStyle := vsReport)。不,没有这样的功能。你必须自己写一个。 [如果您改用 TListBox,这将是微不足道的,但我猜您需要这些列。]
  • 那么,轮班项目的解决方案是什么?你能给我举个例子吗?
  • 直到我读到这篇文章,我才从标题中想到这个问题与Shift-UpShift-Down 的击键有关。连字符在这里似乎不合适并且非常具有误导性。但我不是英语老师,所以我可能只需要从这个案例中学到一些新东西。

标签: delphi listview items


【解决方案1】:

没有经常使用 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;

【讨论】:

  • 多选呢?大概 Kermia 不需要那个。
  • 另外,拥有两个几乎相同的例程也很痛苦。编写一个例程,让它接收一个参数来确定它是向上还是向下移动。
  • @David:我也不喜欢重复的代码。当我尝试帮助某人时,我的首要任务是确保代码有效并且足够完整,以便可以在最少的假设下使用它。我觉得我已经实现了这个目标,所以我把重构留给了用户。
  • listview中位置为1时代码不起作用。这是代码的流程,当我们单击向上按钮时,焦点首先转移到选定的列 -1,然后调用 KeyUp 事件处理程序。解决这个问题的方法是什么?
【解决方案2】:

你有两个选择:

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

我执行第一个选项的例程是这样的:

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 方法用于填充列表视图的列。

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

【讨论】:

  • Source 包含要移动的项目。它们被移动到出现在Target 之前。您需要对其进行重新设计以适合您的代码,向您展示代码的目的是表达想法,而不是为您提供可以“按原样”使用的东西。但是,如果您可以做一个虚拟列表视图,那就更好了。
猜你喜欢
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多