Выберите несколько строк при Shift+ клик в DBGrid

Мне нужно написать код для выбора нескольких строк на Shift+MouseClick, чтобы я мог заполнить значения. Есть ли способ, которым я могу это сделать? Мои параметры DBGrid следующие:

 dbGrid1.Options = [dgEditing, dgAlwaysShowEditor, dgTitles, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit, dgMultiSelect]

2 ответа

Первоначально я думал, что проблема, с которой вы, вероятно, столкнетесь, заключается в том, что Shift + Click обрабатывается самой сеткой, поэтому во время срабатывания OnMouseUp сетки сетка уже переместила курсор набора данных в строку, которая была нажата с помощью Shift, Поэтому расширение выделения сетки с того места, где оно находилось до нажатия на клавишу Shift, не будет простым, поскольку вам не хватит информации о том, где ранее находился курсор ds.

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

Для простоты я реализовал это с помощью ClientDataSet с полем целочисленного идентификатора. Смысл использования поля идентификатора состоит в том, что код использует текущие и предыдущие значения идентификатора, что-то вроде ручной передачи, когда набор данных прокручивается, для своей работы. Делать подобное с использованием закладок было бы сложнее из-за необходимости постоянно выделять и освобождать их, поэтому я оставляю это как упражнение для читателя.

Код:

//  Form variables
  SettingBookmarkRange : Boolean;
  CurrentRowID,
  PreviousRowID: Integer;

procedure TForm1.CDS1AfterScroll(DataSet: TDataSet);
begin
  if SettingBookmarkRange then exit;
  PreviousRowID := CurrentRowID;
  CurrentRowID := CDS1.FieldByName('ID').AsInteger;
  Caption := Format('Current %d, prior %d', [CurrentRowID, PreviousRowID]);
end;

procedure TForm1.SetBookmarkRange;
var
  BM,
  TempBM : TBookmark;
  NewBM : TBookmarkStr;
  FoundPrevious : Boolean;
begin

  //  This code is called after the user does a Shift-Click in the grid
  //  First we set a flag to temporarily prevent the CurrrentRowID and
  //  PreviousrowID from being updated during the dataset's OnScroll event
  SettingBookmarkRange := True;

  BM := CDS1.GetBookmark;

  //  Set a flag to keep track of whether we've found the row with the PreviousRowID
  FoundPrevious := False;
  try
    CDS1.DisableControls;

    //  First, search forwards to see if we can find the the row with the PreviousRowID
    //  In other words, we're first checking that the Shift-Click was on a row *above*
    //  the previous row
    CDS1.Next;
    while not FoundPrevious and not CDS1.Eof do begin
       if CDS1.FieldByName('ID').AsInteger = PreviousRowID then begin
         FoundPrevious := True;

         //  We found the row with the PreviousRowID, so now get the Grid to add it, and
         //  all the rows back to where we started, in its SelectedRows list
         while not CDS1.Bof and (CDS1.FieldByName('ID').AsInteger <> CurrentRowID) do begin
           DBGrid1.SelectedRows.CurrentRowSelected := True;
           CDS1.Prior;
         end;
      end
       else
         CDS1.Next;
    end;
    if not FoundPrevious then begin
      //  If we get here, the Shift-Click must have been in a row further down the
      //  grid than the previously-current one
      while not FoundPrevious and not CDS1.Bof do begin
        if CDS1.FieldByName('ID').AsInteger = PreviousRowID then begin
          FoundPrevious := True;
         //  We found the row with the PreviousRowID, so now get the Grid to add it, and
         //  all the rows back to where we started, in its SelectedRows list
          while not CDS1.Eof and (CDS1.FieldByName('ID').AsInteger <> CurrentRowID) do begin
            DBGrid1.SelectedRows.CurrentRowSelected := True;
            CDS1.Next;
          end;
        end
        else
          CDS1.Prior;
      end;
    end;
  finally
    CDS1.GotoBookmark(BM);
    CDS1.FreeBookmark(BM);
    CDS1.EnableControls;
    SettingBookmarkRange := False;
  end;
end;

procedure TForm1.DBGrid1MouseUp(Sender: TObject; Button: TMouseButton; Shift:
    TShiftState; X, Y: Integer);
begin
  Caption := IntToStr(CDS1.Fields[0].Value);
  if ssShift in Shift then
    SetBookMarkRange;
end;

Я использовал вставку для TDBGrid class, Работает с клавишами Ctrl+Shift:

type
  TDBGrid = class(Vcl.DBGrids.TDBGrid)
  private
    procedure SelectRange;
  protected
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  end;

  {...}

implementation

  {...}
procedure TDBGrid.SelectRange;
var
  CurrentBookMark, CursorBookMark, FirstBookMark, LastBookMark: TBookmark;
  Dir: integer;
begin
  if SelectedRows.Count <= 1 then
    exit;

  DataSource.DataSet.DisableControls;
  try
    FirstBookMark := SelectedRows.Items[0];
    LastBookMark := SelectedRows.Items[SelectedRows.Count - 1];
    SelectedRows.Clear;
    CurrentBookMark := DataSource.DataSet.GetBookmark;
    Dir := DataSource.DataSet.CompareBookmarks(FirstBookMark, CurrentBookMark);

    if Dir = 0 then
      Dir := DataSource.DataSet.CompareBookmarks(LastBookMark, CurrentBookMark);

    if Dir > 0 then
      DataSource.DataSet.GotoBookmark(LastBookMark)
    else if Dir < 0 then
      DataSource.DataSet.GotoBookmark(FirstBookMark)
    else
      Exit;

    while not DataSource.DataSet.eof do
    begin
      CursorBookMark := DataSource.DataSet.GetBookmark;
      SelectedRows.CurrentRowSelected := true;

      if DataSource.DataSet.CompareBookmarks(CurrentBookMark, CursorBookMark) = 0 then
      begin
        DataSource.DataSet.FreeBookMark(CursorBookMark);
        break;
      end;
      DataSource.DataSet.FreeBookMark(CursorBookMark);

      if Dir < 0 then
        DataSource.DataSet.Next
      else
        DataSource.DataSet.Prior;
    end;

    DataSource.DataSet.FreeBookMark(CurrentBookMark);
  finally
    DataSource.DataSet.EnableControls;
  end;
end;

{ TDBGrid }


procedure TDBGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  inherited;
  if Shift = [ssCtrl, ssShift, ssLeft] then
    SelectRange;
end;

Поведение выбора по умолчанию для сетки с несколькими выборками -Ctrl-Click, а не Shift-Click. Для его использования не требуется никаких специальных обработчиков щелчков мышью.

Чтобы реализовать Shift-Click вместо этого, вы должны отменить / реализовать обработчики щелчков мыши в сетке.

Другие вопросы по тегам