Как установить активную ячейку в TDBGrid?

Я хочу активировать ячейку в TDBGrid по коду. Под «активировать» я подразумеваю, что пользователь щелкнул внутри ячейки, готовый отредактировать содержимое ячейки. Как я мог это сделать?

Редактировать: это, вероятно, включает два шага: изменить текущую активную ячейку, затем войти в режим редактирования.


person Heinrich Ulbricht    schedule 02.11.2011    source источник


Ответы (2)


Если вы имеете в виду «активировать режим редактирования для текущей активной ячейки», вам, вероятно, следует сделать следующее:

MyDBGrid.EditorMode := True;

Активировать конкретную ячейку можно либо через SelectedIndex:

MyDBGrid.SelectedIndex := 2;  { or maybe MyDBGrid.SelectedIndex + 1 }

или через SelectedField:

MyDBGrid.SelectedField := MyDataSet.FieldByName('Name');

Чтобы определить, какая ячейка находится под курсором мыши в данный момент, вы можете использовать MouseCoord, который возвращает запись TGridCoord, содержащую координаты ячейки под курсором. Поле TGridCoord.X можно использовать непосредственно для установки активного столбца сетки.

var
  Cell: TGridCoord;

...

Cell := MyDBGrid.MouseCoord(X, Y);
MyDBGrid.SelectedIndex := Cell.X;

Установить строку сложнее, и пока единственный способ, который я смог найти, включает в себя так называемый защищенный взлом, метод доступа к защищенным свойствам и методам класса. И это класс TDBGrid, который нам нужно «взломать».

По сути, вы объявляете пустого потомка TDBGrid, например:

type
  THackDBGrid = class(TDBGrid);

Затем, когда вам нужно получить доступ к защищенному свойству или методу, вы просто приводите экземпляр стандартного класса (в данном случае MyDBGrid) к «взломанному» типу (THackDBGrid):

… THackDBGrid(MyDBGrid).protected_property_or_method

Нас интересует свойство Row. Он возвращает координату Y активной строки. Нам нужно знать это, чтобы определить разницу между активной строкой и строкой под курсором, чтобы мы могли соответствующим образом переместить указатель записи базового набора данных. Вот как:

MyDataSet.MoveBy(Cell.Y - THackDBGrid(MyDBGrid).Row);

Значение Row не является абсолютным: оно относится к видимой верхней строке, но так же относится и TGridCoord.Y, поэтому разница между ними соответствует разнице между строками данных в базовом наборе данных.

Одна вещь, которую я хотел бы подчеркнуть: этот защищенный метод взлома следует использовать осторожно. Защищенные элементы защищены по причине. Так что, если вы можете избежать этого, пожалуйста, сделайте это. И если вы не можете (другого пути нет или это помогает вам делать что-то намного проще), не забудьте воздержаться от каких-либо изменений напрямую с помощью защищенного хака. Я имею в виду, что все может быть в порядке, но обычно вы никогда не знаете наверняка. Как видите, я использовал этот метод только для чтения защищенного содержимого, ничего не меняя напрямую. Состояние объекта было в конечном итоге изменено, но это было результатом стандартного механизма, запущенного методом MoveBy.

Вы можете прочитать больше о защищенном взломе здесь .

person Andriy M    schedule 02.11.2011
comment
Мне нужно сначала изменить текущую активную ячейку - вот где я застрял. (В частности, мне нужна ячейка под курсором мыши.) Я отредактировал вопрос, чтобы уточнить это. - person Heinrich Ulbricht; 02.11.2011
comment
@HeinrichUlbricht: обновлен способ поиска ячейки под курсором мыши. - person Andriy M; 02.11.2011
comment
Приближаемся :) Y по-прежнему игнорируют. Мне нужно иметь возможность свободно указывать выбранную ячейку, включая строку и столбец (или X и Y). - person Heinrich Ulbricht; 02.11.2011
comment
@HeinrichUlbricht: Да, это предвиделось. Установка строки будет намного сложнее. Хорошо, тогда вернемся к чертежной доске. - person Andriy M; 02.11.2011

Моя реализация основана на отличной детективной работе Андрея:

type
  TDBGridAccess = class(TDBGrid);

// Set the currently active grid cell to (DestCol, DestRow). Both values are
// relative to the currently _visible_ upper left grid cell.
procedure SelectDBGridCell(Grid: TDBGrid; DestCol, DestRow: Integer);
var
  CurrentRow: Integer;
begin
  if not Assigned(Grid.DataSource) or not Assigned(Grid.DataSource.DataSet) then
    Exit;

  CurrentRow := TDBGridAccess(Grid).Row;
  Grid.DataSource.DataSet.MoveBy(DestRow-CurrentRow);
  // check if the leftmost grid column is the indicator column which has no
  // equivalent field in the dataset
  if dgIndicator in Grid.Options then
    Grid.SelectedIndex := DestCol-1 else
    Grid.SelectedIndex := DestCol;
end;

procedure TDBGridController.HandleDBGridMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  CellAtMousePos: TGridCoord;
  CurrentRow: Integer;
  DBGrid: TDBGrid;
begin
  DBGrid := Sender as TDBGrid;
  CellAtMousePos := DBGrid.MouseCoord(X, Y);
  if (CellAtMousePos.X<>-1) and (CellAtMousePos.Y<>-1)  then
    SelectDBGridCell(DBGrid, CellAtMousePos.X, CellAtMousePos.Y);
end;

(Выбор сетки следует за курсором мыши. Но SelectDBGridCell можно также использовать для выбора ячейки на основе других критериев.)

Работает как шарм с технической точки зрения. Юзабилити - другой вопрос.

person Heinrich Ulbricht    schedule 17.11.2011