IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

TDBGrid et TDataSet/AfterScroll


Sujet :

Delphi

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2008
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 26
    Points : 13
    Points
    13
    Par défaut TDBGrid et TDataSet/AfterScroll
    Bonjour,

    J'utilise un DBGrid dans une fiche, celui est relié à un DataSet (ADOQuery) situé dans un DataModule, jusque-là rien de plus basique.

    Je souhaiterais afficher ou masquer un bouton de la fiche en fonction de la valeur d'un champ de l'enregistrement en cours dans le DBGrid. Le code serait le suivant par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    myButton.Visible := (ADOQuery1.FieldByName('Type').AsString = 'A') ;
    J'aurais besoin de faire cela dans un événement déclenché lors du changement de ligne du DBGrid mais il n'en existe pas au niveau du DBGrid !!! On ne peut qu'utiliser les événements BeforeScroll/AfterScroll du TDataSet mais mon problème est que le DataSet est dans une autre unité (DataModule) qui n'a pas accès au bouton...

    Que faire ?

  2. #2
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 235
    Points : 8 504
    Points
    8 504
    Par défaut
    Utilises le OnChange du Datasource qui lie ton DbGrid au Dataset

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2008
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 26
    Points : 13
    Points
    13
    Par défaut
    Tu souhaites sans doute parler de l'événement "OnDataChange" du DataSource ?
    Si tel est le cas, cela me pose deux problèmes :
    - cet événement est également déclenché lors de n'importe quelle modification sur l'enregistrement.
    - le DataSource est aussi déporté dans le DataModule !

    Après quelques recherches, voici une solution qui semble fonctionner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Type TForm1 = class(TForm)
        procedure FormShow(Sender: TObject);
      private    
        procedure myAfterScrollEvent(Sender: TDataSet);
      public
     
      end;
     
    procedure TForm1.FormShow(Sender: TObject); //Association de l'événement à la procédure locale
    begin
      DataModule1.ADOQuery1.AfterScroll := myAfterScrollEvent;
    end
    procedure TForm1.myAfterScrollEvent(Sender: TDataSet); //Implémentation de la procédure locale
    begin
      myButton.Visible := (DataModule1.ADOQuery1.FieldByName('Type').AsString = 'A') ;
    end
    Je ne suis pas très à l'aise avec la manipulation des événements ; j'espère que la méthode est bonne. Quelqu'un peut-il donner son avis ?

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 705
    Points : 25 575
    Points
    25 575
    Par défaut
    A peu de chose près, j'ai aussi ce type de comportement dans l'objet ancêtre de tous les objets grilles de l'application que je maintiens pour changer le Visible et surtout le Enabled des boutons (Ajout\Modif\... selon aussi des droits du login)

    Si tu utilises un TDataModule globale
    Pense à retirer le AfterScroll dans le FormDestroy
    car c'est un risque de violation d'accès à la libération du MyButton alors que l'on utilise toujours le Query ailleurs
    D'ailleurs, je le ferais plutôt dans le FormCreate plutôt que FormShow !

    En plus, si tu as des "cascades" de fenêtre, la modification AfterScroll doit mémoriser le précédent Gestionnaire puis le rétablir ...
    autant avoir un ADOQuery dédié à l'affichage qui n'est manipulé que la TForm concernée !
    Le DataModule peut devenir un piège avec ce genre de détail, encore pire si l'on ouvre plusieurs fenêtres sur le même Query, cela peut-être le chaos total !


    Personnellement, je préfère créer mes Query au moment opportun avec le SQL adéquat pour éviter des interactions entre les objets, souvent encapsuler dans objets métiers (avec l'expérience, tu y viendras peut-être un jour ou même jamais comme de nombreux développeurs)

  5. #5
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 235
    Points : 8 504
    Points
    8 504
    Par défaut
    Citation Envoyé par Vyns1520 Voir le message
    Tu souhaites sans doute parler de l'événement "OnDataChange" du DataSource ?
    Si tel est le cas, cela me pose deux problèmes :
    - cet événement est également déclenché lors de n'importe quelle modification sur l'enregistrement.
    - le DataSource est aussi déporté dans le DataModule !

    Après quelques recherches, voici une solution qui semble fonctionner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Type TForm1 = class(TForm)
        procedure FormShow(Sender: TObject);
      private    
        procedure myAfterScrollEvent(Sender: TDataSet);
      public
     
      end;
     
    procedure TForm1.FormShow(Sender: TObject); //Association de l'événement à la procédure locale
    begin
      DataModule1.ADOQuery1.AfterScroll := myAfterScrollEvent;
    end
    procedure TForm1.myAfterScrollEvent(Sender: TDataSet); //Implémentation de la procédure locale
    begin
      myButton.Visible := (DataModule1.ADOQuery1.FieldByName('Type').AsString = 'A') ;
    end
    Je ne suis pas très à l'aise avec la manipulation des événements ; j'espère que la méthode est bonne. Quelqu'un peut-il donner son avis ?
    Attention avec le onAfterScroll avec certain composant lors du remplissage de la grille, il est appelé après chaque affichage. De plus lors de l'utilisation de la molette dans la grille, il est sollicité aussi sur tous les éléments qu'il parcours (J'ai eu des problème de lenteur dans un code que je dois maintenir à cause de cela)

    Avec le OnDataChange. Il n'est appelé que lors le curseur du dataset est stabilité.
    Pour ton problème lors de l'édition il suffit de rajouter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    If not TDataSource(Sender).State in [dsEdit, dsInsert] then
      // Ton code

  6. #6
    Membre à l'essai
    Inscrit en
    Juin 2008
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 26
    Points : 13
    Points
    13
    Par défaut
    Merci à tous les deux !

    Dans mon cas, l'événement "AfterScroll" se déclenche exactement comme il faut..
    J'ai donc également ajouté une ligne pour dissocier l'événement de ma procédure locale à la fermeture de ma fenêtre car cela provoquait effectivement des exceptions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TForm1.FormDestroy(Sender: TObject)
    begin
      DataModule1.ADOQuery1.AfterScroll := nil ;
    end;
    D'ailleurs, je le ferais plutôt dans le FormCreate plutôt que FormShow !
    Peux-tu stp m'expliquer ce que cela change d'utiliser "FormCreate" plutôt que "FormShow" ou pourquoi pas "FormClose" au lieu de "FormDestroy" pour la dissociation par exemple ?

    Personnellement, je préfère créer mes Query au moment opportun avec le SQL adéquat pour éviter des interactions entre les objets, souvent encapsuler dans objets métiers
    Si je comprends bien, en conception, tu ne créés que le DataSource qui est associé à tes composants liés aux données (DBEdit, DBGrid, etc...) ? Et c'est à l'exécution que tu instancies le DataSet (création du composant + ouverture) pour terminer avec une ligne "DataSource1.DataSet := DataSet1" ?

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 705
    Points : 25 575
    Points
    25 575
    Par défaut
    Citation Envoyé par Vyns1520 Voir le message
    Peux-tu stp m'expliquer ce que cela change d'utiliser "FormCreate" plutôt que "FormShow" ou pourquoi pas "FormClose" au lieu de "FormDestroy" pour la dissociation par exemple ?
    Tout simplement parce que tu peux créer une fenêtre SANS l'afficher, oui, c'est un peu idiot mais possible
    Surtout que FormCreate et FormDestroy ne sont appelés qu'une fois dans le cycle de vie d'une instance alors que FormShow, FormClose si l'on joue avec Show(), Hide() et Close() et rappelons que CloseAction est par défaut à caHide, du coup, cela peut être appelé plusieurs fois dans cycle de vie d'une instance et cela peut amener des effets de bords !

    Je préfère pour ce genre de manipulation les FormCreate et FormDestroy mais c'est une habitude car je surchargeais souvent Constructor\Destructor en Delphi, pratique obligatoire depuis que je suis passé sous C++Builder

    Citation Envoyé par Vyns1520 Voir le message
    Si je comprends bien, en conception, tu ne créés que le DataSource qui est associé à tes composants liés aux données (DBEdit, DBGrid, etc...) ?
    Tout à fait, le DataSource est posé sur la fenêtre, car souvent il ne sert qu'a cela
    J'évite de mélanger un DataSource pour l'affichage et les DataSource pour Master\Detail (faut dire que je n'en fait quasiment jamais préférant une structure objet métier)

    Citation Envoyé par Vyns1520 Voir le message
    Et c'est à l'exécution que tu instancies le DataSet (création du composant + ouverture) pour terminer avec une ligne "DataSource1.DataSet := DataSet1" ?
    Comme dans le code là : Création dynamique TADODataSet

    En fait, j'ai une couche objet qui me gère les IO avec la DB (full SQL) un peu comme Bold, InstantsObjects, ECO ...

    Mes objets métierd peuvent fonctionner
    - avec un DataSet interne (indispensable avec le mode DataSource)
    - un mode allégé où le DataSet a été lu, recopié dans des membres privés et libéré, cela évite de conserver des Cursor SQL, c'est bien plus léger en mémoire, valeur typée plus léger que collection de TField

    Mes objets métiers peuvent être associés à un DataSource pour faciliter l'affichage via DBEdit, DBCheckBox ... (un jour j'étudierais les LiveBindings)
    Le DataSource est double emploi d'ailleurs

    Si DataSet interne à l'objet, il fourni ses données internes (un seul record), c'est en général une fiche "DETAIL"
    Si Pas de DataSet interne à l'objet, il utilise les données du DataSource et un fourni une sorte de curseur sur un ensemble de record, idéal pour les DBGrid avec un code toujours encapsulé pour accéder à des fonctionnalités utilisant la DB pour son paramètrage mais faisant bien plus que cela (je pilote essentiellement du matos)

  8. #8
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    A peu de chose près, j'ai aussi ce type de comportement dans l'objet ancêtre de tous les objets grilles de l'application que je maintiens pour changer le Visible et surtout le Enabled des boutons (Ajout\Modif\... selon aussi des droits du login)

    Si tu utilises un TDataModule globale
    Pense à retirer le AfterScroll dans le FormDestroy
    car c'est un risque de violation d'accès à la libération du MyButton alors que l'on utilise toujours le Query ailleurs
    D'ailleurs, je le ferais plutôt dans le FormCreate plutôt que FormShow !

    En plus, si tu as des "cascades" de fenêtre, la modification AfterScroll doit mémoriser le précédent Gestionnaire puis le rétablir ...
    autant avoir un ADOQuery dédié à l'affichage qui n'est manipulé que la TForm concernée !
    Le DataModule peut devenir un piège avec ce genre de détail, encore pire si l'on ouvre plusieurs fenêtres sur le même Query, cela peut-être le chaos total !
    +1
    Citation Envoyé par ShaiLeTroll Voir le message
    Personnellement, je préfère créer mes Query au moment opportun avec le SQL adéquat pour éviter des interactions entre les objets, souvent encapsuler dans objets métiers (avec l'expérience, tu y viendras peut-être un jour ou même jamais comme de nombreux développeurs)
    pas d'accord, car les query surtout les ado sera mieux crée avec le constructeur de delphi à la création de la fenêtre, sa facilite aussi les liaison des champs à la conception

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 705
    Points : 25 575
    Points
    25 575
    Par défaut
    Citation Envoyé par edam Voir le message
    sa facilite aussi les liaison des champs à la conception
    En quoi cela facilite-t-il la conception pour la liaison des champs ?

    Si liaison DBControls : TDataSource et TDBEdit\TDBGrid ... sont parfaitement relié ensemble, DataField est parfois* renseigné (oui pas de combo pour choisir, il suffit de copier-coller)
    Avoir un Query ouvert durant le Design Time n'apporte pas grand chose surtout si il s'agit d'un TClientDataSet alimenté par un Provider distant via Midas-DataSnap !

    Si liaison Master-Detail, ce n'est pas la coutume de l'équipe que j'ai rejoints, je suis les directives de mon responsable, j'ai proposé cette approche, une fois pour un collègue, cela simplifiait largement son code mais c'est bien la seule fois que cela a été mis en place

    * le DataField est parfois* renseigné, n'est-ce pas étrange !

    Historiquement, l'application que je maintiens ne contient rien en dur
    , car DataField est souvent renseigné en RunTime via des fichiers de config séparé, un peu compliqué à mon gout mais c'est le choix technique de mon responsable !

    Il aurait pu pousser un peu plus le précepte de ré-utilisabilité POO
    Effectivement, les grilles sont toutes héritées de la même ancêtre, il y a un héritage systématique, alors qu'au final, il suffit de changer le SQL, fournir les bon DataField au DBGrid avec les bons titres, un seul écran partagé pour plusieurs listings, c'est bien pour avoir une ergonomie identique dans toute l'application

    J'ai fait une petite ORM, une couche objet type InstantObjects ou ECO qui gère la transition modèle relationnel <-> modèle OO et donc me simplifie grandement la vie en automatisant certains éléments manuel de ces fichiers de config

  10. #10
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut Changement d'enregistrement
    Bonjour,

    Une solution simple pour régler ce problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
    begin
      IF Sender = NIL THEN exit;
      IF Form1 = NIL THEN exit;
      IF Field <> NIL THEN exit;
      DisplayButton;
    end;
     
    procedure DisplayButton;
    begin
    myButton.Visible := (ADOQuery1.FieldByName('Type').AsString = 'A') ;
    end;

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 705
    Points : 25 575
    Points
    25 575
    Par défaut
    Citation Envoyé par cantador Voir le message
    IF Field <> NIL THEN exit;
    Bien vu !

    Data.DB.TDataChangeEvent :
    Le paramètre Field spécifie le champ ayant été affecté, si seul un champ a été ciblé. Field est défini sur null si la modification peut affecter plus d'une valeur de champ (par exemple, lors du déplacement sur un nouvel enregistrement ou l'actualisation d'un tampon d'enregistrement).
    Par contre IF Sender = NIL THEN exit; me semble TRES PEU probable !

    Par contre IF Form1 = NIL THEN exit; si l'on considère Form1 comme un Singleton avec une affectation à nil dans son OnDestroy, pourquoi pas mais cela ne résoud pas les problèmes de cascade de fenêtre !
    D'ailleurs, que vaut Self, si l'on libère la fenêtre et que l'on affecte à nil, si le OnDataChange traine, Self sera à nil, c'est le principe du couple Free qui protège le Destroy

  12. #12
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut
    En fait, la seule instruction importante est juste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IF Sender = NIL THEN exit;
    Cela fait un bail que j'utilise ce procédé car il y a un cas où cette instruction est nécessaire.
    Mais, je n'arrive plus à retrouver le contre exemple ! (elle est bonne celle-là..)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IF Field <> NIL THEN exit;
    est mise par précaution car il est difficile d'imaginer toutes les situations possibles..

    quant à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if form1 = Nil then exit;
    peut-être omise puisque si la forme qui contient le DataSet n'est pas créée l'évènement n'a pas lieu.
    mais en revanche, je la conserverai pour la forme qui contient le bouton
    (cf: question de Vyns1520)

    Enfin, les déclenchements intempestifs du OnDataChange peuvent se régler
    par l'utilisation de tout un ensemble de petites astuces selon la
    configuration de l'application et aussi comme l'indique Rayek à
    l'aide d'un test sur l'état du Dataset.

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 705
    Points : 25 575
    Points
    25 575
    Par défaut
    Citation Envoyé par cantador Voir le message
    En fait, la seule instruction importante est juste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IF Sender = NIL THEN exit;
    Cela fait un bail que j'utilise ce procédé car il y a un cas où cette instruction est nécessaire.
    Mais, je n'arrive plus à retrouver le contre exemple ! (elle est bonne celle-là..)

    Sender à nil ???
    Si l'on regarde le code du TDataSource, c'est impossible car cela indiquerait un Self à nil (le TDataSource lui même à nil, une belle VA00000000 lors de l'accès au DataLinks) hors le problème de Vyns1520 n'est pas que le TDataSource est à nil mais le Self du Event Handler donc plutôt Form1

    Extrait du code du TDataSource dans Data.DB.pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ...
            if Assigned(FOnDataChange) then FOnDataChange(Self, nil);
    ...
     if Assigned(FOnDataChange) then FOnDataChange(Self, TField(Info));
    ...
    Difficile d'avoir un Sender<=>Self à nil


    Citation Envoyé par cantador Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IF Field <> NIL THEN exit;
    est mise par précaution car il est difficile d'imaginer toutes les situations possibles..
    Tu te mélanges les pinceaux !
    C'est clairement écrit dans l'aide de Data.DB.TDataChangeEvent :
    Le paramètre Field spécifie le champ ayant été affecté, si seul un champ a été ciblé. Field est défini sur null si la modification peut affecter plus d'une valeur de champ (par exemple, lors du déplacement sur un nouvel enregistrement ou l'actualisation d'un tampon d'enregistrement).
    Citation Envoyé par cantador Voir le message
    quant à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if form1 = Nil then exit;
    peut-être omise puisque si la forme qui contient le DataSet n'est pas créée l'évènement n'a pas lieu.
    Dommage, ce n'est pas le cas de Vyns1520 dont le DataSet est dans un DataModule et semble que malgré notre proposition d'isoler les DataSet dédié à l'affichage, Vyns1520 semble ne pas avoir suivi, d'ailleurs, cela fait 10 jours qu'il a obtenu une réponse satisfaisante, je pense qu'il ne nous lit plus !
    il a oublié le bouton !

    En fait, justement, c'est l'inverse que j'expliquais avec l'affectation AfterScroll à nil, c'est que l'on a crée la Forme puis que l'on a détruit celle-ci, il faut donc retire le lien entre le TDataSource\TDataSet vers un EventHandler dont l'objet receveur va être libéré

  14. #14
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    tu peut aussi avoir autant de TDatasourcde liée à un seul composant Tdataset
    comme sa tu peut avoir un autre sur ta forme, et utilisé son événement ondatachange
    bon dev

  15. #15
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut
    Bonjour,

    J'utilise un DBGrid dans une fiche, celui est relié à un DataSet (ADOQuery) situé dans un DataModule, jusque-là rien de plus basique.

    Je souhaiterais afficher ou masquer un bouton de la fiche en fonction de la valeur d'un champ de l'enregistrement en cours dans le DBGrid. Le code serait le suivant par exemple :

    Code :
    Sélectionner tout - Visualiser dans une fenêtre à part

    1
    2



    myButton.Visible := (ADOQuery1.FieldByName('Type').AsString = 'A') ;

    J'aurais besoin de faire cela dans un événement déclenché lors du changement de ligne du DBGrid mais il n'en existe pas au niveau du DBGrid !!! On ne peut qu'utiliser les événements BeforeScroll/AfterScroll du TDataSet mais mon problème est que le DataSet est dans une autre unité (DataModule) qui n'a pas accès au bouton...

    Que faire ?
    je viens d'écrire vite fait sur le gaz, une petite appli
    avec un DataModule (qui n'est qu'une forme particulière..)
    contenant un TDataSource et un TDataset et une autre forme contenant un bouton que je rends visible selon certaines valeurs du query.

    et tout marche bien

    mais je maintiens le IF Sender = NIL THEN exit;
    foi de cantador

    il faut juste que je retrouve le cas véreux..(peut-être en mode réseau)

    Vyns1520 a prolongé ses vacances de Pâques
    c'est dommage.

  16. #16
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    Citation Envoyé par cantador Voir le message

    mais je maintiens le IF Sender = NIL THEN exit;
    foi de cantador

    il faut juste que je retrouve le cas véreux..(peut-être en mode réseau)

    Vyns1520 a prolongé ses vacances de Pâques
    c'est dommage.
    si tu appel toi même la procedure avec un paramétre nil

  17. #17
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut
    si tu appel toi même la procedure avec un paramétre nil

  18. #18
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    je m'excuse pour cantador car j'ai suivie ShaiLeTroll
    je confirme que fieldpeut être null dans OnDataChange
    dans l'aide de delphi:
    TDataSource.OnDataChange

    TDataSource Voir aussi Exemple

    Se produit quand les données d'un enregistrement ont été modifiées, en raison de l'édition de champs ou du déplacement du curseur sur un nouvel enregistrement.

    type TDataChangeEvent = procedure(Sender: TObject; Field: TField) of object;
    property OnDataChange: TDataChangeEvent;

    Description

    Un gestionnaire d'événement OnDataChange permet d'effectuer des actions spécifiques quand un champ de l'enregistrement en cours a été modifié et que l'application passe sur un autre champ, ou quand l'enregistrement en cours de l'ensemble de données associé a été modifié. OnDataChange est utile dans les applications devant synchroniser l'affichage de données dans des contrôles qui ne sont pas orientés données. Cet événement est généralement utilisé pour garantir que le contrôle reflète les valeurs de champs en cours de l'ensemble de données, puiqu'il est déclenché par toutes les modifications.

    La méthode Next ou Prior de l'ensemble de données peut déclencher cet événement. Les contrôles orientés données notifient une source de donnés d'une modification des données lors*:

    Du passage à un nouvel enregistrement.
    D'une modification des données d'un champ.

    Le paramètre Field vaut nil si la modification peut affecter plusieurs valeurs de champs (par exemple, lors du déplacement sur un nouvel enregistrement ou de l'actualisation d'un tampon d'enregistrement). Si un seul champ est affecté, Field indique le champ édité.

  19. #19
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut
    pas de souci edam..
    la confrontation, c'est normal.
    et j'aime ça en plus.

    et merci pour ce rappel sur le OnDataChange

    @bientôt

  20. #20
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 705
    Points : 25 575
    Points
    25 575
    Par défaut
    Citation Envoyé par edam Voir le message
    je m'excuse pour cantador car j'ai suivie ShaiLeTroll
    je confirme que fieldpeut être null dans OnDataChange
    dans l'aide de delphi:
    Je n'ai jamais dit le contraire !
    Merci de ne pas déformer mes propos !

    edam, tu as mal lu mes propos et ceux de cantador puisque le débat concerne le Sender et non le Field

    J'ai même cité l'aide deux fois et j'ai même fourni le DEUX formes d'appel de OnDataChange dans le TDataSource :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     if Assigned(FOnDataChange) then FOnDataChange(Self, nil);
     if Assigned(FOnDataChange) then FOnDataChange(Self, TField(Info));
    Sender à nil me semble TRES difficile car indiquerait un OnDataChange émit par un TDataSource (Self) libéré !

    Field à nil est prévu par la spécification de OnDataChange et n'a donc rien de surprenant !

Discussions similaires

  1. TDBGRID - Couleur de fond d'une seule cellule
    Par cgo dans le forum Bases de données
    Réponses: 5
    Dernier message: 11/09/2009, 11h16
  2. Table Access et Accents dans TDBGrid
    Par puzpuz_vannes dans le forum Bases de données
    Réponses: 3
    Dernier message: 13/11/2003, 23h23
  3. [TDBGrid] Multisélection de lignes pour suppression
    Par littledoudou dans le forum C++Builder
    Réponses: 9
    Dernier message: 05/11/2003, 11h42
  4. Réponses: 19
    Dernier message: 27/08/2003, 16h32
  5. Dimensions des colonnes d'un TDBGrid
    Par osmose22 dans le forum C++Builder
    Réponses: 4
    Dernier message: 11/12/2002, 12h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo