AfterScroll и AfterOpen в TQuery - PullRequest
       63

AfterScroll и AfterOpen в TQuery

0 голосов
/ 21 декабря 2018

В моем приложении есть компонент TQuery, в котором мне нужно что-то делать в событии AfterScroll ():

void __fastcall TFormMain::Query1AfterScroll(TDataSet *DataSet)
{
    // do stuff here...
}

Проблема заключается в том, что событие AfterScroll явно запускается дважды, когда я делаю следующее:

Query1->Active = true; // first call to AfterScroll 
Query1->Locate( /* some arguments here */ ); // second call

Примечание. Модификация SQL-запроса вместо Locate () НЕТ опции

Первый вызов AfterScroll - это тот, который я не хочу обрабатывать, поэтому я ищу элегантный способтолько для обработки второго.

Одной из моих первых идей было использование события AfterOpen () для подключения обработчика событий AfterScroll на лету:

__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
    Query1->AfterScroll = 0;
}

void __fastcall TFormMain::Query1AfterOpen(TDataSet *DataSet)
{
     Query1->AfterScroll = Query1AfterScroll;
}

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

Редактировать:

Я знаю, что мог бы установить некоторыефлаги для подавления кода в AfterScroll из Executing (что я и делаю сейчас (и: как это описано в первом ответе ниже)), но я думаю, что должен быть более элегантный и менее подверженный ошибкам способ.

Но после некоторого исследования я боюсь, что лучшего решения нет.

Мой вопрос сейчас:

Как правильнопоймать правильный вызов AfterScroll?(тот, который вызывается после Locate (...))

1 Ответ

0 голосов
/ 21 декабря 2018

Код Delphi ниже переопределяет стандартное поведение TAdoQuery (но должно работать с любым другим потомком TDataSet, который поддерживает Locate()), так что событие AfterScroll является только , вызываемым сразу после вызоваTAdoQuery.Locate.

По сути, он переопределяет TAdoQuery DoAfterScroll, поэтому унаследованный метод вызывается только при установленном логическом флаге FHandleScrollAfterLocate.DoAfterScroll - это метод TDataSet, который используется для вызова любого настроенного обработчика AfterScroll.Флаг установлен в True в переопределенной функции Locate и очищается каждый раз, когда вызывается DoAfterScroll.

Я уверен, что вы поймете, если хотите изменить условия, при которых AfterScrollназывается.

  type
    TAdoQuery = class(ADODB.TAdoQuery)
    private
      FHandleScrollAfterLocate: Boolean;
    protected
      property HandleScrollAfterLocate : Boolean read FHandleScrollAfterLocate;
      function Locate(const KeyFields: string; const KeyValues: Variant;
        Options: TLocateOptions): Boolean; override;
      procedure DoAfterScroll; override;
    public
    end;

    TForm1 = class(TForm)
      DataSource1: TDataSource;
      DBGrid1: TDBGrid;
      DBNavigator1: TDBNavigator;
      ADOConnection1: TADOConnection;
      AdoQuery1: TADOQuery;
      AdoQuery1ID: TIntegerField;
      AdoQuery1name: TStringField;
      btnLocate: TButton;
    [etc]
    [...]

    { TAdoQuery }

    procedure TAdoQuery.DoAfterScroll;
    begin
      try
        if FHandleScrollAfterLocate then
          inherited;
      finally
        FHandleScrollAfterLocate := False;
      end;
    end;

    function TAdoQuery.Locate(const KeyFields: string;
      const KeyValues: Variant; Options: TLocateOptions): Boolean;
    begin
      FHandleScrollAfterLocate := True;
      Result := inherited Locate(KeyFields, KeyValues, Options);
    end;

    procedure TForm1.AdoQuery1AfterScroll(DataSet: TDataSet);
    begin
      Caption := 'Scrolled';
    end;

    procedure TForm1.btnLocateClick(Sender: TObject);
    begin
      AdoQuery1.Locate('ID', 5, []);
    end;
...