Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.08.27;
Скачать: CL | DM;

Вниз

Событие "AfterOpen" в TDBGrid   Найти похожие ветки 

 
AlexAA   (2010-02-24 11:38) [0]

Добрый день!

Как в TDBGrid"e поймать момент выполнения запроса? А еще лучше момент, когда запрос только выполнился и данные получены.
Уточню: DataSet"ом является TADOQuery.


 
12 ©   (2010-02-24 11:59) [1]

ну так наверное и нужно смотреть ADOQuery1AfterOpen


 
AlexAA   (2010-02-24 12:59) [2]


> 12 ©   (24.02.10 11:59) [1]
> ну так наверное и нужно смотреть ADOQuery1AfterOpen


Так в том и дело, что нужно определить событие в TDBGrid"e.

В ADOQuery не подходит.

Другими словами, как grid узнает, о том, что записи загружены и их нужно отобразить?

В исходниках не нашел ничего похожего на то, что Query сообщает grid"y о том, что надо отобразить записи.


 
Медвежонок Пятачок ©   (2010-02-24 13:04) [3]

Так в том и дело, что нужно определить событие в TDBGrid"e.

Чтобы у грида было событие афтероупен, у него сначала должен появиться метод Оупен.
Чтобы был момент когда уже АфтерОупен настало.


 
12 ©   (2010-02-24 13:08) [4]

у грида есть FDataLink: TGridDataLink;
а там
TGridDataLink = class(TDataLink)
 private
   FGrid: TCustomDBGrid;
далее  вызывается FGrid/DataChange


> В ADOQuery не подходит.

почему?


 
Ega23 ©   (2010-02-24 13:39) [5]


> Так в том и дело, что нужно определить событие в TDBGrid"e.
> В ADOQuery не подходит.
>
> Другими словами, как grid узнает, о том, что записи загружены
> и их нужно отобразить?
>
> В исходниках не нашел ничего похожего на то, что Query сообщает
> grid"y о том, что надо отобразить записи.


В общем "академическом" случае - никак. У TDataSet есть метод DisableControls и парный ему EnableControls. Суть такова, что если было выставлено DataSet.DisableControls, то при любых событиях TDataSet (изменение позиции курсора, добавлении-изменении-удалении записей, переоткрытии запроса) данные события не доходят до всех TDataSource, которые "смотрят" на твой TDataSet.
Соответственно, при "включении" TDataSet.EnableControls во все DB-Aware контролы приходит событие OnDataChange.
Поэтому в общем случае узнать нельзя.

ИМХО, это не совсем правильно, что разработчики VCL не ввели дополнительное событие в DataSource (или в DataLink), что в DataSet был вызван EnableControls. Геморроя добавляется очень много, особенно в случае компонентов типа TDBTreeView (когда требуется полный набор данных, зафетченный до конца, дабы дерево правильно можно было построить).


 
Ega23 ©   (2010-02-24 13:45) [6]

А, ну и вдогонку: DataSet понятия не имеет о том, сколько различных контролов на него "смотрит" (и смотрит ли вообще). DataSet знает только список TDataSource, которые "смотрят" на него. И при своих внутренних событиях (если не включено DisableControls) DataSet транслирует эти события всему списку TDataSource.
Соответственно, все TDataSource понятия не имеют о природе компонентов, которые "смотрят" на него, у него есть список TDataLink, которым DataSource перетранслирует полученные события от TDataSet.
Ну а уж как ты свой потомок DataLink организуешь - это твоё личное дело.
К примеру, у меня когда-то давно был написан невизуальный компонент TDBImageList, который работал как стандартный, но картинки сосал из базы.


 
AlexAA   (2010-02-24 14:22) [7]


> Ega23 ©   (24.02.10 13:45) [6]


Спасибо за подробное разъяснение.

Значит мне нужно переделать TGridDataLink под себя.
Потребутеся перекрыть TDataLink.DataEvent.

Реально ли как-то подменить privat"ный FDataLink или придется переписывать весь TCustomDBGrid (такая задача передо мной ставится впервые) ?


 
Ega23 ©   (2010-02-24 14:30) [8]

Я думаю, что тебе для решения твоей частной задачи достаточно будет завязаться на события TDataSource.
Ты лучше опиши саму задачу, бо народу тут опытного дофига, наверняка твою задачу уже кто-то решал.
DBGrid с нуля отрисовывать ты умучаешься, факт.


 
Ega23 ©   (2010-02-24 14:41) [9]

Сейчас перечитал твой вопрос. Вобщем, попробуй завязаться на TDataSource.OnStateChange, где проанализируй свойство State.
Но, опять же, это не избавит тебя от проблемы TDataSet.DisableControls/ TDataSet.EnableControls


 
AlexAA   (2010-02-24 14:44) [10]

Да, действительно случай частный.
Ловить открытие датасета нужно для построения некоева подкомпонента для внутренних нужд. В этом подкомпоненте парсится весь текст запроса на составные части. В общем эти данные нужны только в двух случаях: 1) При поднятии формы выбора полей сортировки. 2) При клике с альтом на заголовоке.

Просто не хотелось каждый раз чистить подкомпонент и заполнять снова. Хотя процессорного время на это уходит не так уж много.


 
Anatoly Podgoretsky ©   (2010-02-24 14:52) [11]


> Так в том и дело, что нужно определить событие в TDBGrid"e.
>
>
> В ADOQuery не подходит.

А в TDBGrid"e нет ни данных, ни зпросов. AfterOpen датасета как раз нужное событие. Датасет уже открыт *выполнен запрос и открыта таблица.


 
Ega23 ©   (2010-02-24 14:54) [12]


> Ловить открытие датасета нужно для построения некоева подкомпонента
> для внутренних нужд. В этом подкомпоненте парсится весь
> текст запроса на составные части. В общем эти данные нужны
> только в двух случаях: 1) При поднятии формы выбора полей
> сортировки. 2) При клике с альтом на заголовоке.
>


Понятно. Вобщем так, ИМХО - подход в корне неверный, т.к. я вполне могу вместо текста "Select .... from .... Order By ....." вызывать какую-нибудь хранимку.
Это раз.
Никто не застрахован от запроса Select Фамилия + " " + Имя + " " + Отчество as ФИО Order By Фамилия, Имя, Отчество
Т.е. сортировка по трём реальным полям в БД, но в финальном наборе данных - одно поле.
Это два.
Посмотри в сторону TDBGrid.Columns[Index].FieldName
Это три.


 
AlexAA   (2010-02-24 15:31) [13]


> т.к. я вполне могу вместо текста "Select .... from ....
> Order By ....." вызывать какую-нибудь хранимку.
> Это раз.
> Никто не застрахован от запроса Select Фамилия + " " + Имя
> + " " + Отчество as ФИО Order By Фамилия, Имя, Отчество
> Т.е. сортировка по трём реальным полям в БД, но в финальном
> наборе данных - одно поле.
> Это два.
> Посмотри в сторону TDBGrid.Columns[Index].FieldName
> Это три.


Вот как раз от пункта 3 пытаюсь уйти, т.к. если "select t1.Name as Name1, t2.Name as Name2 from t1, t2 where... order by TDBGrid.Columns[1].FieldName" выдаст ошибку на сервере.

Пункт 1 и 2 не принципиален, т.к. grid не на отдачу(продажу), а для меня.


 
AlexAA   (2010-02-24 15:33) [14]

еще нужен алиас таблицы. как раз этим и занимается класс "TSQLFields"


 
Ega23 ©   (2010-02-24 15:36) [15]


> еще нужен алиас таблицы. как раз этим и занимается класс
> "TSQLFields"


Посмотри на такую конструкцию

Select T1.Field1, T2.Field2
 from Table1 T1, Table2 T2
 where ....
 Order By 1;


 
AlexAA   (2010-02-25 08:45) [16]


> Посмотри на такую конструкцию
>
> Select T1.Field1, T2.Field2
>  from Table1 T1, Table2 T2
>  where ....
>  Order By 1;


Тоже врядли подойдет, потому что колонки могут перемещаться, а после перемещения уже не представится возможным определить точно по какой колонке была сортировка. Хотя этот способ действительно упростит жизнь, например можно хранить список TList на TColumns, по которым осуществляется сортировка + нужно донавернуть TList по поводу направления сортировки(Asc, Desc)


 
Ega23 ©   (2010-02-25 08:48) [17]

А ещё у TADODataSet есть свойство Sort


 
sniknik ©   (2010-02-25 09:36) [18]

> такая задача передо мной ставится впервые
я тебя наверное разочарую, но задача до сих пор не озвучена, то что ты тут преподносишь как задачу на самом деле методы решения (до сих пор не пойми чего).ф


 
12 ©   (2010-02-25 10:04) [19]


> Ловить открытие датасета нужно для построения некоева подкомпонента
> для внутренних нужд

а что если добавить в этот подкомпанент ссылку на ADOQuery и чиститься/парсится по возникновению события афтеопен привязанного к нему ADOQuery


 
12 ©   (2010-02-25 11:05) [20]

Покритикуйте. Ногами тоже можно :)

 TMyParse = class
   FQ:TADOQuery;
   foo:procedure(ds:tdataset);
 public
   Constructor Create(AQ:TadoQuery);
   procedure Parse(DataSet: TDataSet);
 end;

-----
procedure TForm1.Button1Click(Sender: TObject);
var MP:TMyParse;
begin
  MP:=TMyParse.Create(ADOQuery1);
end;

constructor TMyParse.Create(AQ: TadoQuery);
begin
 FQ:=AQ;
 foo:=addr(FQ.AfterOpen);
 FQ.AfterOpen:=Parse;
end;

procedure TMyParse.Parse(DataSet: TDataSet);
begin
showmessage("TMyParse.Parse work");
if addr(foo) <> nil then foo(DataSet);
end;


 
Ega23 ©   (2010-02-25 11:12) [21]


> Покритикуйте. Ногами тоже можно :)


Нафига FQ нужно?


 
12 ©   (2010-02-25 11:23) [22]


> Нафига FQ нужно?

всмысле Create(var ADOQuery1); ?


 
Ega23 ©   (2010-02-25 12:43) [23]


> всмысле Create(var ADOQuery1); ?


А зачем var? Ты собираешься менячть значение указателя ADOQuery1?


 
12 ©   (2010-02-25 12:50) [24]


> А зачем var? Ты собираешься менячть значение указателя ADOQuery1?

дык у меня FQ.AfterOpen:=Parse;
а можно  что_передали. AfterOpen:=Parse; тогда var и без FQ

но не нравится что-то мне это. Чувствую что фигня :)


 
Ega23 ©   (2010-02-25 13:13) [25]


> дык у меня FQ.AfterOpen:=Parse;


И чо? А у меня плита газовая.


 
12 ©   (2010-02-25 13:21) [26]

получил ADOQUERY. Надо его метод афтеопен дополнить
можно FQ направить на ADOQUERY и работать с FQ
можно с самим переданным ADOQUERY, но тогда как var его передавать


 
Ega23 ©   (2010-02-25 13:31) [27]


> можно с самим переданным ADOQUERY, но тогда как var его
> передавать


Уверен?


 
12 ©   (2010-02-25 14:01) [28]

работает

type
 TForm1 = class(TForm)
   ADOConnection1: TADOConnection;
   ADOQuery1: TADOQuery;
   DataSource1: TDataSource;
   DBGrid1: TDBGrid;
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
   procedure ADOQuery1AfterOpen(DataSet: TDataSet);
 private
   { Private declarations }
 public
   { Public declarations }
 end;
TMyParse = class
 // FQ:TADOQuery;
  foo:procedure(ds:tdataset);
public
  Constructor Create(var AQ:TadoQuery);
  procedure Parse(DataSet: TDataSet);
end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

{ TMyParse }

procedure TForm1.Button1Click(Sender: TObject);
var MP:TMyParse;
begin
 MP:=TMyParse.Create(ADOQuery1);
end;

constructor TMyParse.Create(var AQ: TadoQuery);
begin
//FQ:=AQ;
foo:=addr(AQ.AfterOpen);
AQ.AfterOpen:=Parse;
end;

procedure TMyParse.Parse(DataSet: TDataSet);
begin
showmessage("TMyParse.Parse work");
if addr(foo) <> nil then foo(DataSet);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ADOQuery1.Close;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ADOQuery1.open;
end;

procedure TForm1.ADOQuery1AfterOpen(DataSet: TDataSet);
begin
showmessage("");
end;


 
Ega23 ©   (2010-02-25 15:16) [29]


> 12 ©   (25.02.10 14:01) [28]
>
> работает


Не сомневаюсь. А если var убрать из конструктора?  :)))


 
имя   (2010-02-25 15:48) [30]

Удалено модератором
Примечание: п. 5 правил



Страницы: 1 вся ветка

Текущий архив: 2010.08.27;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.072 c
2-1268741673
Вася
2010-03-16 15:14
2010.08.27
Destructor


2-1267947335
tippa
2010-03-07 10:35
2010.08.27
по структуре LVITEM


2-1267715582
ZV
2010-03-04 18:13
2010.08.27
Инвертировать определенный бит в байте. Как ?


15-1271921592
АлександрВторой
2010-04-22 11:33
2010.08.27
Отчеты в базах данных в Delphi 2009


2-1272870252
Виктор
2010-05-03 11:04
2010.08.27
could not find program