Использует ли TUniQuery (UniDa c TUniQuery) методы Last и First для прямого перехода или выполнения записи путем прокрутки записи - PullRequest
0 голосов
/ 26 мая 2020

У меня есть программа, которая должна настраивать более менее сложный экран после того, как пользователь перейдет к определенной записи в наборе данных (TUniQuery). Пользователь может выбирать разными способами: поле со списком, поле поиска и, наконец, DbNavigator. Переход от первой до последней записи занимает вечность. После выполнения программы я обнаружил, что нажатие последней кнопки на DBNavigator вызывает посещение каждой записи в наборе данных, и поэтому для каждой из них экран строится без толку. То же самое для любой записи, идущей к первой или последней. Насколько я понимаю, такие методы ( First и Last ) будут делать прямой переход. Возможно, это особенное поведение компонентов Unida c, но я не могу найти ни ссылки, ни свойства для его изменения. В настоящее время я планирую установить флаг для события BeforeScroll , но, поскольку AfterScroll также происходит после каждого из них, я не могу узнать, когда набор данных закончил прокрутку. Я также не могу найти ссылку на документацию Delphi, в которой просто указано
Call Last, чтобы сделать последнюю запись в наборе данных активной

1 Ответ

0 голосов
/ 28 мая 2020

Следуя исходному коду, я нашел это:
Короткий ответ : Да, TDataset переходит непосредственно к первой и последней записи, когда это возможно, но ...

Длинный ответ : Delphi имеет внутренние события данных ( DB unit, TDataEvent ), которые транслируются, поэтому элементы управления с учетом данных могут обновляться должным образом. Такие методы, как Next , Prior и многие другие, используют функцию MoveBy , которая генерирует события Before / AfterScroll , а также внутренние события. MoveBy может при необходимости получить дополнительные строки. Допустим, у вас есть двадцать строк, извлеченных из набора данных из тридцати строк. Ваш текущий рекорд - пятнадцать. Вы звоните MoveBy (2) . Как и ожидалось, ваш новый рекорд - семнадцать. В этом случае происходит следующее:

  1. BeforeScroll
  2. ActiveRecord увеличивается дважды (в al oop), но строки не выбираются
  3. Internal DataEvent: deDataSetScroll
  4. AfterScroll

Обратите внимание, что при прокрутке не происходит никаких программных событий. BeforeScroll встречается на пятнадцатой записи и AfterScroll на семнадцатой.

Теперь тот же сценарий, но на этот раз вызывается MoveBy (10) . Уже выбраны пять строк (20–15), и необходимо получить еще пять. В этом случае последовательность следующая:

  1. BeforeScroll
  2. ActiveRecord увеличивается на пять (в al oop), но строки не выбираются
  3. Активная запись увеличивается на пять, там же l oop. В каждом цикле выбирается запись (программных событий не происходит)
  4. внутреннее событие DataEvent: deDataSetChange
  5. AfterScroll

Все работает нормально . Проблема возникает с методом Last , который не использует MoveBy и предполагает, что записи были всегда извлечены:

procedure TDataSet.Last;  
begin  
  CheckBiDirectional;  
  CheckBrowseMode;  
  DoBeforeScroll;  
  ClearBuffers;  
  try
    InternalLast;  
    GetPriorRecord;  
    GetPriorRecords;  
  finally  
    FEOF := True;  
    DataEvent(deDataSetChange, 0);  // Problem! Causes TJvDBSearchComboBox to retrieve all records (again)
    DoAfterScroll;  
  end;  
end;  

Как вы можете см. метод Last всегда транслирует событие deDataSetChange , даже если все записи были извлечены . В моем конкретном случае с четырьмя записями пользователь нажимает последнюю кнопку TDBNavigator , которая, в свою очередь, вызывает метод Last . Событие deDataSetChange транслируется, а затем TJvDBSearchComboBox (из библиотеки JVCL) реагирует на это событие, посещая каждую строку с «while not eof ... next» l oop для обновления его содержимого и создания событий Before / AfterScroll .

Мне нравится Delphi, но это одна из вещей, которые мне не нравятся в наборах данных. Программа не может узнать, было ли инициировано определенное событие данных из-за действия пользователя или самой программы. В презентациях Delphi я предлагал способ перемещения по набору данных без запуска событий (как это делает MoveBy ), а затем такие компоненты, как TJvDBSearchComboBox , могли бы его использовать, или как минимум флаг или что-то подобное в наборе данных, который можно было бы включить перед началом посещения каждой записи. Кроме того, Last должен проверить, действительно ли были получены записи.

Некоторые скажут, что это легко реализовать самостоятельно, и это действительно так, когда ваш код прокручивает набор данных. Но в случае TDBNavigator и TJvDBSearchComboBox я не могу их контролировать. Кто-то другой скажет, что не используйте JVCL, здесь нет простого ответа. Кроме того, к вашему сведению, метод First демонстрирует такое же поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...