cxgrid выделение (или цвет) измененной ячейки в закрытом запросе формы

При закрытии формы у меня есть:

if MessageDlg('Close program ?',
          mtConfirmation, [mbYes,mbCancel],0) <> mrYes then CanClose := False
else if DataModule2.mytable.State in [dsEdit,dsInsert] then
               if MessageDlg('Save changes ?', mtConfirmation,
                    [mbYes,mbNo],0) = mrYes then DataModule2.mytable.Post;

Есть ли способ выделить (или раскрасить) измененную ячейку в cxgrid при запуске события onclosequery?

Мне не нужно знать, что было изменено, мне просто нужно знать, какая ячейка была изменена, чтобы пользователь мог ее видеть, чтобы он мог легко решить, будет ли погода сохранять изменения или нет.


person user763539    schedule 29.06.2016    source источник
comment
Думаю, вам, возможно, придется более подробно объяснить, чего вы пытаетесь достичь. Что делать, если несколько столбцов в одной строке были изменены? Когда вы говорите "изменено", вы имеете в виду включить изменения, уже сохраненные в наборе данных? Ваш набор данных выполняет ApplyUpdates () s?   -  person MartynA    schedule 29.06.2016
comment
Да, я хотел бы выделить каждую ячейку во всей строке, если она была изменена. Это до события публикации, поэтому еще ничего не сохранено. Сетка находится в режиме [dsEdit, dsInsert]. Нет, база данных не вызывает applyupdates.   -  person user763539    schedule 29.06.2016
comment
Это ситуация, когда пользователь изменяет таблицу, забывает опубликовать изменения и пытается закрыть форму. Поэтому, прежде чем он закроет форму (и потеряет все измененные данные), неплохо сказать ему, что изменения, которые он внес в таблицу, еще не сохранены, и показать ему (ячейки), которые были изменены. Понимать ? Я думал, возможно, о раскраске измененной ячейки, чтобы ее было легко видно, хотя подсветка тоже в порядке.   -  person user763539    schedule 29.06.2016
comment
Я не уверен, но думаю, что эта функция была встроена в TMS ADVgrid. Если вы измените символ в строке, сетка выделит его. Каждое изменение в строке было выделено. очень приятная особенность.   -  person user763539    schedule 29.06.2016


Ответы (1)


С помощью события cxGrid1DBTableView1CustomDrawCell легко заставить cxGrid рисовать ячейку (или строку), выделенную каким-либо образом. И имея флаг, который указывает, что событие OnCloseQuery выполняется, вы можете ограничить его действие внутри этого события.

Обновить. Код, который я изначально разместил вместе с этим ответом, не смог успешно пометить более одной ячейки в текущей строке сетки как измененные. Однако обновленный код ниже может это сделать; обратите внимание на комментарии в двух процедурах.

type
  TForm1 = class(TForm)
    [...]
  public
    QueryingClose : Boolean;
  end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  try
    QueryingClose := True;
    //{cxGrid1.Invalidate{True);  Do NOT call Invalidate, because it causes the
    //  grid's repainting logic to operate in a way which effectively makes it
    //  impossible to mark more that one cell in the current data row as changed
    ShowMessage('Close?');
  finally
    QueryingClose := False;
  end;
end;

procedure TForm1.cxGrid1DBTableView1CustomDrawCell(Sender:
    TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo:
    TcxGridTableDataCellViewInfo; var ADone: Boolean);
var
  Field : TField;
  MarkCell : Boolean;
  S1,
  S2 : String;
  EC : TcxGridTableEditingController;
begin
  if QueryingClose  and
    (TcxGridDBTableView(Sender).DataController.DataSet.State in[dsEdit, dsInsert]) then begin
    Field := TcxGridDBColumn(AViewInfo.Item).DataBinding.Field;
    S1 := VarToStr(Field.OldValue);

    //  When this event is called, the user may be in the middle of editing a cell's contents
    //  So, the purpose of the following lines is to close the inplace editor being used to do
    //  this amd post the chamged value back to the TField associated with the cell
    EC :=  TcxGridDBTableView(Sender).Controller.EditingController;
    if EC.IsEditing then
      EC.HideEdit(True);

    S2 := VarToStr(Field.Value);
    MarkCell := S1 <> S2;
    if MarkCell then
      ACanvas.Brush.Color := clLime;
  end;
end;

Чтобы это работало, ваш тип-потомок TDataSet должен поддерживать правильный возврат исходного содержимого полей в свойстве OldValue; TClientDataSet, который я использовал для написания / тестирования этого кода, безусловно, делает это, но я понятия не имею, какой именно тип TDataSet вы используете.

Надеюсь, должно быть очевидно, что вы можете использовать эти две процедуры для создания списка TFields, значения которых изменились, включая FieldName OldValue и Value.

person MartynA    schedule 29.06.2016
comment
Это не выделяет измененные ячейки, если вы переходите из измененной ячейки в другую. Он выделяет только последнюю посещенную ячейку в строке независимо от того, была она изменена или нет. - person user763539; 29.06.2016
comment
Извините, я оставил детали реализации на ваше усмотрение. Вы спросили, есть ли способ выделить (или раскрасить) измененную ячейку - мой ответ показывает, как выделить / раскрасить ячейку специально во время события OnCloseQuery. Имо, вам решать, является ли данная клетка кандидатом на особую обработку или нет. - person MartynA; 29.06.2016
comment
Я попытаюсь добавить конкретный пример обнаружения того, что значение поля, связанного с данной ячейкой, изменилось немного позже. - person MartynA; 29.06.2016
comment
с нетерпением жду ... Спасибо! - person user763539; 29.06.2016
comment
Смотрите обновление. Как всегда, навигация по объектам и свойствам cxGrid требует некоторой производительности! - person MartynA; 29.06.2016
comment
Этот новый код работает так же, как и предыдущий. Не вижу разницы. - person user763539; 01.07.2016
comment
Не уверен, что следую: в исходной версии моего кода ячейка в фокусе была отмечена, потому что набор данных находится в состоянии dsEdit / dsInsert. Таким образом, ячейка в фокусе была отмечена независимо от того, было ли изменено ее содержимое. В обновленном коде он помечается только в том случае, если его содержимое было изменено - см. Последнее обновление, чтобы узнать, как проверить и пояснить. Пометка каждой ячеек, в которых изменились значения, будет намного сложнее, imo, и потребует, чтобы ваш тип набора данных поддерживал доступ к исходным значениям в полях. - person MartynA; 01.07.2016
comment
Не обращайте внимания на мои комментарии к этому ответу - обновленная версия должна делать то, о чем, как я понимаю, вы просите. - person MartynA; 01.07.2016
comment
Если я попытаюсь отредактировать пустую ячейку, а затем уйду, то у меня будет неприятное нарушение прав доступа ... Но, неважно ... Я доволен исходным кодом. Только что добавлено при закрытом запросе: cxGrid1DBTableView1.Controller.FocusedRow.MakeVisible; на случай, если измененное не в фокусе. - person user763539; 02.07.2016
comment
Я не могу спровоцировать этот AV, нужны точные шаги для воспроизведения. - person MartynA; 02.07.2016