Delphi: Shift-Up и Shift-Down в списке

Есть ли в элементе управления Listview функция для перемещения элементов вверх и вниз?


person Kermia    schedule 13.03.2011    source источник
comment
Судя по названию, язык — Delphi, а судя по языку — ОС Windows.   -  person Kermia    schedule 13.03.2011
comment
Прошу прощения, я обычно проверяю теги для таких вещей. Скорее всего, его пропустят, если поставить в конце заголовка (в круглых скобках).   -  person Marcelo Cantos    schedule 13.03.2011
comment
@Kermia: Вы забыли сказать, что используете элемент управления в режиме отчета (ViewStyle := vsReport). Нет, такой функции нет. Вы должны написать один самостоятельно. [Это было бы тривиально, если бы вместо этого вы использовали TListBox, но я предполагаю, что вам нужны столбцы.]   -  person Andreas Rejbrand    schedule 13.03.2011
comment
Итак, каково решение для сменных элементов? не могли бы вы привести мне пример?   -  person Kermia    schedule 13.03.2011
comment
Пока я не прочитал пост, я подумал из заголовка, что вопрос связан с нажатиями клавиш Shift-Up и Shift-Down. Дефисы кажутся здесь неуместными и вводят в заблуждение. Но я не преподаватель английского языка, поэтому, возможно, мне просто нужно узнать что-то новое из кейса.   -  person Andriy M    schedule 13.03.2011
comment
@Andriy: Shift-Down не похож на Shift + Down   -  person Kermia    schedule 14.03.2011
comment
@Kermia: я знаю, что последний шаблон теперь считается стандартом для указания нажатий клавиш, но я все еще очень хорошо помню времена, когда это было не так. Shift-Up было таким же правильным и распространенным обозначением, как и Shift+Up. А для клавиш управления вы можете дополнительно иметь ^Up. Как бы то ни было, теперь я узнал, что «shift-up» вполне может быть правильной грамматикой для существительного. Так что вина в том, что я запутался, в любом случае лежит на мне. :)   -  person Andriy M    schedule 14.03.2011


Ответы (2)


Не очень много работая с 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;
person crefird    schedule 13.03.2011
comment
Как насчет множественного выбора? Предположительно, Кермии это не нужно. - person David Heffernan; 13.03.2011
comment
Также больно иметь две практически одинаковые программы. Напишите одну подпрограмму и заставьте ее получать параметр, чтобы определить, перемещается ли она вверх или вниз. - person David Heffernan; 13.03.2011
comment
@David: мне также не нравится повторяющийся код. Когда я пытаюсь кому-то помочь, мой приоритет — убедиться, что код работает и достаточно полон, чтобы его можно было использовать с минимальными предположениями. Я чувствовал, что достиг этой цели, поэтому оставил рефакторинг на усмотрение пользователя. - person crefird; 14.03.2011
comment
Код не работает, когда позиция 1 в списке. Это поток для кода, когда мы нажимаем кнопку вверх, фокус сначала перемещается на выбранный столбец -1, а затем вызывается обработчик события KeyUp. Каков обходной путь для этого? - person siddharth taunk; 05.05.2016

У вас есть два варианта:

  • Удалите их, а затем снова вставьте на новое место.
  • Используйте представление виртуального списка и перемещайте их в своей структуре данных.

Моя процедура для выполнения первого из этих вариантов выглядит следующим образом:

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 используется для заполнения столбцов представления списка.

Это прекрасный пример того, почему виртуальные элементы управления так хороши.

person David Heffernan    schedule 13.03.2011
comment
Source содержит элементы, которые нужно переместить. Они перемещены, чтобы появиться перед Target. Вам нужно будет переработать его, чтобы он вписался в ваш код, цель показать вам код состоит в том, чтобы выразить идею, а не дать вам то, что вы можете использовать как есть. Однако, если бы вы могли сделать виртуальный список, это было бы лучше. - person David Heffernan; 13.03.2011