Les gestionnaires d’événements propagent les modifications en dehors du modèle

Dans le Kit de développement logiciel (SDK) visualisation et modélisation, vous pouvez définir des gestionnaires d’événements de stockage pour propager les modifications apportées aux ressources en dehors du magasin, telles que des variables, des fichiers, des modèles dans d’autres magasins ou d’autres extensions Visual Studio. Les gestionnaires d’événements du magasin sont exécutés après la fin de la transaction dans laquelle l’événement déclencheur s’est produit. Ils sont également exécutés dans le cadre d'une opération Annuler ou Rétablir. Par conséquent, contrairement aux règles de magasin, les événements de magasin sont les plus utiles pour mettre à jour les valeurs qui se trouvent en dehors du magasin. Contrairement aux événements .NET, les gestionnaires d’événements de magasin sont inscrits pour écouter une classe : vous n’avez pas besoin d’inscrire un gestionnaire distinct pour chaque instance. Pour plus d’informations sur la façon de choisir entre différentes façons de gérer les modifications, consultez Réponse aux modifications et propagation des modifications.

La surface graphique et d’autres contrôles de l’interface utilisateur sont des exemples de ressources externes qui peuvent être gérées par les événements du magasin.

Pour définir un événement de magasin

  1. Choisissez le type d’événement que vous souhaitez surveiller. Pour obtenir une liste complète, examinez les propriétés de EventManagerDirectory. Chaque propriété correspond à un type d’événement. Les types d’événements les plus fréquemment utilisés sont les suivants :

    • ElementAdded - déclenché lorsqu’un élément de modèle, un lien de relation, une forme ou un connecteur est créé.

    • ElementPropertyChanged - déclenché lorsque la valeur d’une Normal propriété de domaine est modifiée. L’événement est déclenché uniquement si les valeurs nouvelles et anciennes ne sont pas égales. L’événement ne peut pas être appliqué aux propriétés de stockage calculées et personnalisées.

      Elle ne peut pas être appliquée aux propriétés de rôle qui correspondent aux liens de relation. Utilisez plutôt ElementAdded pour surveiller la relation de domaine.

    • ElementDeleted - déclenché après la suppression d’un élément de modèle, d’une relation, d’une forme ou d’un connecteur. Vous pouvez toujours accéder aux valeurs de propriété de l’élément, mais elle n’aura aucune relation avec d’autres éléments.

  2. Ajoutez une définition de classe partielle pour YourDslDocData dans un fichier de code distinct dans le projet DslPackage .

  3. Écrivez le code de l’événement en tant que méthode, comme dans l’exemple suivant. Cela peut être static, sauf si vous souhaitez accéder à DocData.

  4. Redéfinissez OnDocumentLoaded() pour enregistrer le gestionnaire. Si vous avez plusieurs gestionnaires, vous pouvez les inscrire tous au même endroit.

L’emplacement du code d’inscription n’est pas critique. DocView.LoadView() est un autre emplacement.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;

namespace Company.MusicLib
{
  partial class MusicLibDocData
  {
    // Register store events here or in DocView.LoadView().
    protected override void OnDocumentLoaded()
    {
      base.OnDocumentLoaded(); // Don't forget this.

      #region Store event handler registration.
      Store store = this.Store;
      EventManagerDirectory emd = store.EventManagerDirectory;
      DomainRelationshipInfo linkInfo = store.DomainDataDirectory
          .FindDomainRelationship(typeof(ArtistAppearsInAlbum));
      emd.ElementAdded.Add(linkInfo,
          new EventHandler<ElementAddedEventArgs>(AddLink));
      emd.ElementDeleted.Add(linkInfo,
          new EventHandler<ElementDeletedEventArgs>(RemoveLink));

      #endregion Store event handlers.
    }

    private void AddLink(object sender, ElementAddedEventArgs e)
    {
      ArtistAppearsInAlbum link = e.ModelElement as ArtistAppearsInAlbum;
      if (link != null)
            ExternalDatabase.Add(link.Artist.Name, link.Album.Title);
    }
    private void RemoveLink(object sender, ElementDeletedEventArgs e)
    {
      ArtistAppearsInAlbum link = e.ModelElement as ArtistAppearsInAlbum;
      if (link != null)
            ExternalDatabase.Delete(link.Artist.Name, link.Album.Title);
    }
  }
}

Utiliser des événements pour effectuer des ajustements non modifiables dans le Windows Store

Les événements de magasin ne sont normalement pas utilisés pour propager les modifications à l’intérieur du magasin, car le gestionnaire d’événements s’exécute une fois la transaction validée. Au lieu de cela, vous utiliseriez une règle de magasin. Pour plus d’informations, consultez Comment les règles propagent des modifications dans le modèle.

Toutefois, vous pouvez utiliser un gestionnaire d’événements pour effectuer des mises à jour supplémentaires dans le magasin, si vous souhaitez que l’utilisateur puisse annuler les mises à jour supplémentaires séparément de l’événement d’origine. Par exemple, supposons que les caractères minuscules sont la convention habituelle pour les titres d’album. Vous pouvez écrire un gestionnaire d’événements de magasin qui corrige le titre en minuscules une fois que l’utilisateur l’a tapé en majuscules. Toutefois, l’utilisateur peut utiliser la commande Annuler pour annuler votre correction, en restaurant les caractères majuscules. Une deuxième annulation supprimerait la modification de l’utilisateur.

En revanche, si vous avez écrit une règle de magasin pour effectuer la même chose, le changement de l’utilisateur et votre correction se trouveraient dans la même transaction, afin que l’utilisateur ne puisse pas annuler l’ajustement sans perdre la modification d’origine.

partial class MusicLibDocView
{
    // Register store events here or in DocData.OnDocumentLoaded().
    protected override void LoadView()
    {
      /* Register store event handler for Album Title property. */
      // Get reflection data for property:
      DomainPropertyInfo propertyInfo =
        this.DocData.Store.DomainDataDirectory
        .FindDomainProperty(Album.TitleDomainPropertyId);
      // Add to property handler list:
      this.DocData.Store.EventManagerDirectory
        .ElementPropertyChanged.Add(propertyInfo,
        new EventHandler<ElementPropertyChangedEventArgs>
             (AlbumTitleAdjuster));

      /*
      // Alternatively, you can set one handler for
      // all properties of a class.
      // Your handler has to determine which property changed.
      DomainClassInfo classInfo = this.Store.DomainDataDirectory
           .FindDomainClass(typeof(Album));
      this.Store.EventManagerDirectory
          .ElementPropertyChanged.Add(classInfo,
        new EventHandler<ElementPropertyChangedEventArgs>
             (AlbumTitleAdjuster));
       */
      return base.LoadView();
    }

// Undoable adjustment after a property is changed.
// Method can be static since no local access.
private static void AlbumTitleAdjuster(object sender,
         ElementPropertyChangedEventArgs e)
{
  Album album = e.ModelElement as Album;
  Store store = album.Store;

  // We mustn't update the store in an Undo:
  if (store.InUndoRedoOrRollback
      || store.InSerializationTransaction)
      return;

  if (e.DomainProperty.Id == Album.TitleDomainPropertyId)
  {
    string newValue = (string)e.NewValue;
    string lowerCase = newValue.ToLowerInvariant();
    if (!newValue.Equals(lowerCase))
    {
      using (Transaction t = store.TransactionManager
            .BeginTransaction("adjust album title"))
      {
        album.Title = lowerCase;
        t.Commit();
      } // Beware! This could trigger the event again.
    }
  }
  // else other properties of this class.
}

Si vous écrivez un événement qui met à jour le magasin :

  • Permet store.InUndoRedoOrRollback d’éviter d’apporter des modifications aux éléments de modèle dans Annuler. Le gestionnaire de transactions réinitialisera tout dans le magasin à son état d'origine.

  • Permet store.InSerializationTransaction d’éviter d’apporter des modifications pendant le chargement du modèle à partir du fichier.

  • Vos modifications entraînent le déclenchement d’autres événements. Veillez à éviter une boucle infinie.

Stocker les types d’événements

Chaque type d’événement correspond à une collection dans Store.EventManagerDirectory. Vous pouvez ajouter ou supprimer des gestionnaires d’événements à tout moment, mais il est habituel de les ajouter lorsque le document est chargé.

EventManagerDirectory Nom de la propriété Exécuté quand
ÉlémentAjouté Une instance d’une classe de domaine, d’une relation de domaine, d’une forme, d’un connecteur ou d’un diagramme est créée.
ÉlémentSupprimé Un élément de modèle a été supprimé du répertoire d’éléments du magasin et n’est plus la source ou la cible d’une relation. L’élément n’est pas réellement supprimé de la mémoire, mais est conservé en cas d’annulation ultérieure.
ElementEventsBegun Appelé à la fin d’une transaction externe.
ElementEventsEnded Appelé lorsque tous les autres événements ont été traités.
ElementMoved Un élément de modèle a été déplacé d’une partition de magasin à une autre.

Cela n’est pas lié à l’emplacement d’une forme sur le diagramme.
ElementPropertyChanged La valeur d’une propriété de domaine a changé. Cela n’est exécuté que si les anciennes et nouvelles valeurs sont inégales.
RôleJoueurModifié L’un des deux rôles (extrémités) d’une relation fait référence à un nouvel élément.
OrdreDesJoueursModifié Dans un rôle ayant une multiplicité supérieure à 1, la séquence de liens a changé.
DébutTransaction
TransactionValidée
TransactionRolledBack

Note

Le Composant de Transformation de modèle de texte est automatiquement installé dans le cadre de la charge de travail de développement d’extensions pour Visual Studio. Vous pouvez également l’installer à partir de l’onglet Composants individuels de Visual Studio Installer, sous la catégorie SDK, bibliothèques et frameworks. Installez le composant sdk de modélisation à partir de l’onglet Composants individuels .