Propagation de modifications en dehors du modèle par des gestionnaires d'événements
Dans le Kit de développement logiciel de visualisation et de modélisation, vous pouvez définir des gestionnaires d'événements du magasin pour propager des modifications apportées aux ressources en dehors de le magasin, telles que les variables de la non-banque, des fichiers, des modèles d'autres magasins, ou d'autres extensions de Visual Studio . Les gestionnaires d'événements du magasin sont exécutés après la fin de la transaction pendant laquelle l'événement de déclenchement s'est produit. Elles sont également exécutées dans une opération d'annulation ou de rétablissement. Par conséquent, contrairement aux règles de le magasin, les événements du magasin sont plus pratiques pour mettre à jour les valeurs qui sont à l'extérieur de le magasin. Contrairement aux événements.NET, les gestionnaires d'événements du magasin sont stockés pour lire une classe : vous ne devez pas stocker un gestionnaire séparé pour chaque instance. Pour plus d'informations sur le choix entre différentes manières de gérer des modifications, consultez Propagation et réponse aux modifications en attente.
La surface graphique et d'autres contrôles d'interface utilisateur sont des exemples de ressources externes qui peuvent être gérées par les événements de le magasin.
Pour définir un événement de le magasin
choisissez le type d'événement que vous souhaitez surveiller. Pour obtenir une liste complète, revue les propriétés d' EventManagerDirectory. chaque propriété correspond à un type d'événement. le plus souvent les types utilisés d'événement sont :
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 propriété de domaine d' Normal est modifiée. L'événement est déclenché que si les nouvelles et anciennes valeurs ne sont pas égales. l'événement ne peut pas être appliqué aux propriétés calculées et personnalisées de stockage.
elle ne peut pas être appliquée au rôle de propriétés qui correspondent aux liens de relation. À la place, utilisez ElementAdded de contrôler la relation de domaine.
ElementDeleted - déclenché après un élément de modèle, une relation, une forme ou un connecteur a été supprimé. Vous pouvez accéder aux valeurs de propriété de cet élément, mais cela n'aura aucun rapport avec d'autres éléments.
Ajoutez une définition de classe partielle pour YourDslDocData dans un fichier distinct de code du projet d' DslPackage .
Écrivez le code de l'événement sous la méthode, comme dans l'exemple suivant. Ce peut être static, sauf si vous souhaitez accéder à DocData.
Substitution OnDocumentLoaded() pour inscrire le gestionnaire. Si vous avez plusieurs handlers, vous pouvez les stocker toutes au même endroit.
L'emplacement du code d'alignement n'est pas importante. 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);
}
}
}
Utilisation des événements pour effectuer des réglages annulable dans le magasin
Les événements du magasin ne sont normalement pas utilisés pour propager des modifications à l'intérieur de le magasin, car le gestionnaire d'événements s'exécute une fois la transaction est requise. À la place, vous utiliseriez une règle de le magasin. Pour plus d'informations, consultez Propagation de modifications dans le modèle par des règles.
Toutefois, vous pouvez utiliser un gestionnaire d'événements pour effectuer des mises à jour supplémentaires au 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, supposez que les minuscules sont la convention standard pour les titres de l'album. Vous pouvez écrire un gestionnaire d'événements du magasin qui corrige le titre à en minuscules après que l'utilisateur a entré en majuscules. Mais l'utilisateur peut utiliser la commande annuler pour annuler vos corrections, restaurant les majuscules. Une deuxième annulation enlèverait la modification de l'utilisateur.
En revanche, si vous avez écrit une règle du magasin de faire de même, la modification de l'utilisateur et vos corrections trouvent dans la même transaction, afin que l'utilisateur n'a pas pu annuler la modification 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 :
Utilisez store.InUndoRedoOrRollback pour éviter d'effectuer des modifications apportées aux éléments de modèle d'annulation. Le gestionnaire de transactions définira tout dans le magasin dans l'état d'origine.
Utilisation store.InSerializationTransaction d'éviter d'apporter des modifications pendant que le modèle est chargé à partir de le fichier.
Vos modifications rend tous les autres événements déclenchés. assurez-vous que vous évitez une boucle infinie.
Types d'événement de le magasin
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 souvent pour les ajouter lorsque le document est chargé.
nom de la propriété d'EventManagerDirectory |
Effectuée lors |
---|---|
ElementAdded |
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. |
ElementDeleted |
Un élément de modèle a été supprimé du répertoire de l'élément du magasin et n'est plus la source ou la cible d'une relation. L'élément n'est pas supprimé réellement de la mémoire, mais est conservé en cas de future annulation. |
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 du magasin à un 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 est exécuté uniquement si les valeurs anciennes et nouvelles sont différentes. |
RolePlayerChanged |
L'un des deux rôles (fins) d'une relation référence un nouvel élément. |
RolePlayerOrderChanged |
Dans un rôle dont la multiplicité est supérieure à 1, la séquence de liens a changé. |
TransactionBeginning |
|
TransactionCommitted |
|
TransactionRolledBack |