Проблемы с перетаскиванием списка при включенном множественном выборе

StackOverflow https://stackoverflow.com/questions/192960

  •  08-07-2019
  •  | 
  •  

Вопрос

У меня есть TListBox с multiselect и ExtendedSelect, для обоих установлено значение true.Мне нужно иметь возможность перетаскивать несколько элементов в списке, чтобы переупорядочить их.Моя проблема заключается в том, что происходит, когда пользователь нажимает на элемент, который уже выбран, не удерживая нажатой клавишу CTRL или SHIFT.

Случай 1:Режим перетаскивания установлен в dmManual Выделение будет удалено до того, как мышь будет нажата.Это не позволит перетаскивать несколько элементов.

Случай 2:Для параметра DragMode установлено значение dmAutomatic Событие MouseDown никогда не срабатывает.Выделение не очищено, поэтому перетаскивание выполняется нормально, но пользователь не может очистить выделение, щелкнув по одному из выбранных элементов.Это действительно вызывает проблему, если выбраны все элементы или следующий элемент, который пользователь хочет выбрать, был частью текущего выбора.

Обратите внимание, что эта проблема возникает только в том случае, если вы назначаете что-либо DragObject в процедуре OnStartDrag.Я думаю, проблема исчезла бы, если бы OnStartDrag запускался только после того, как пользователь перемещал мышь.У меня есть мышь.Установлено значение DragImmediate: = false, но я все равно запускаю startDrag, как только нажимаю на элемент в списке.

Я использую Delphi 7 для этого проекта, но я вижу такое же поведение в Delphi 2007.

Это было полезно?

Решение 4

Я не уверен, почему это имеет значение, но если я изменю DragObject на TDragКонтрольObjectEx (вместо TDR-gobjectex) я получаю поведение, которое я ищу.Режим перетаскивания установлен на Автоматический.

Я попытался разобраться, на что это влияет, но так и не смог в этом разобраться.

Другие советы

Я некоторое время играл с этим.И наблюдайте те же эффекты.

Я бы использовал Case2 и добавил кнопку (Выбрать все / Отменить выбор всего) в список.Это даже добавляет дополнительную функциональность и решает самую неприятную часть проблемы.

Используйте вариант 2 и при срабатывании события TListBox.OnMouseUp проверьте, были ли выбраны и перетаскивались ли несколько элементов.Если выбрано несколько элементов, но они не были перетащены, то отмените выбор всех элементов, кроме выбранного элемента.

Я бы использовал этот метод, потому что проводник Windows работает именно так.

Немного запутанно, но это работает.Режим перетаскивания в списке имеет значение dmAutomatic.

procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  iDropIdx, i: Integer;
  pDropPoint: TPoint;
  slSelected: TStrings;
begin
  {Which item is being dropped onto?}
  pDropPoint := Point(X, Y);
  iDropIdx := ListBox1.ItemAtPos(pDropPoint, False);

  slSelected := TStringList.Create;
  try
    {Copy the selected items to another string list}
    for i := 0 to Pred(ListBox1.Items.Count) do
    begin
      if (ListBox1.Selected[i]) then
        slSelected.Append(ListBox1.Items[i]);
    end;

    {Find the selected items in the listbox and swap them with the drop target}
    for i := 0 to Pred(slSelected.Count) do
    begin
      ListBox1.Items.Exchange(ListBox1.Items.IndexOf(slSelected[i]), iDropIdx);
      inc(iDropIdx);
    end;
  finally
    slSelected.Free;
  end;
end;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top