I gestori eventi propagano le modifiche al di fuori del modello

In Visualization and Modeling SDK è possibile definire gestori eventi di archiviazione per propagare le modifiche alle risorse esterne all'archivio, ad esempio variabili non di archiviazione, file, modelli in altri archivi o altre estensioni di Visual Studio. I gestori eventi di archiviazione vengono eseguiti dopo la fine della transazione in cui si è verificato l'evento di attivazione. Vengono eseguite anche in un'operazione Annulla o Ripeti. Pertanto, a differenza delle regole di archiviazione, gli eventi di archiviazione sono più utili per aggiornare i valori esterni all'archivio. A differenza degli eventi .NET, i gestori eventi dell'archivio vengono registrati per restare in ascolto di una classe: non è necessario registrare un gestore separato per ogni istanza. Per altre informazioni su come scegliere tra modi diversi per gestire le modifiche, vedere Risposta a e propagazione delle modifiche.

La superficie grafica e altri controlli dell'interfaccia utente sono esempi di risorse esterne che possono essere gestite dagli eventi di archiviazione.

Per definire un evento dello Store

  1. Scegliere il tipo di evento da monitorare. Per un elenco completo, esaminare le proprietà di EventManagerDirectory. Ogni proprietà corrisponde a un tipo di evento. I tipi di evento usati più di frequente sono:

    • ElementAdded : attivato quando viene creato un elemento del modello, un collegamento di relazione, una forma o un connettore.

    • ElementPropertyChanged: attivato quando viene modificato il valore di una Normal proprietà di dominio. L'evento viene attivato solo se i valori nuovi e precedenti non sono uguali. L'evento non può essere applicato alle proprietà di archiviazione calcolate e personalizzate.

      Non può essere applicato alle proprietà del ruolo che corrispondono ai collegamenti di relazione. Usare invece ElementAdded per monitorare la relazione di dominio.

    • ElementDeleted : attivato dopo l'eliminazione di un elemento del modello, una relazione, una forma o un connettore. È comunque possibile accedere ai valori delle proprietà dell'elemento, ma non avrà relazioni con altri elementi.

  2. Aggiungere una definizione di classe parziale per YourDslDocData in un file di codice separato nel progetto DslPackage .

  3. Scrivere il codice dell'evento come metodo, come nell'esempio seguente. Può essere static, a meno che non si voglia accedere DocDataa .

  4. Eseguire l'override per registrare OnDocumentLoaded() il gestore. Se si dispone di più gestori, è possibile registrarli tutti nella stessa posizione.

Il percorso del codice di registrazione non è critico. DocView.LoadView() è una posizione alternativa.

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);
    }
  }
}

Usare gli eventi per apportare modifiche annullabili nello Store

Gli eventi di archiviazione non vengono in genere usati per propagare le modifiche all'interno dell'archivio, perché il gestore eventi viene eseguito dopo il commit della transazione. Usare invece una regola di archiviazione. Per altre informazioni, vedere Regole propagate modifiche all'interno del modello.

Tuttavia, è possibile usare un gestore eventi per apportare aggiornamenti aggiuntivi all'archivio, se si vuole che l'utente sia in grado di annullare gli aggiornamenti aggiuntivi separatamente dall'evento originale. Si supponga, ad esempio, che i caratteri minuscoli siano la consueta convenzione per i titoli degli album. È possibile scrivere un gestore eventi dell'archivio che corregge il titolo in lettere minuscole dopo che l'utente lo ha digitato in lettere maiuscole. Tuttavia, l'utente potrebbe usare il comando Annulla per annullare la correzione, ripristinando i caratteri maiuscoli. Un secondo Annulla rimuoverà la modifica dell'utente.

Al contrario, se è stata scritta una regola di archiviazione per eseguire la stessa operazione, la modifica dell'utente e la correzione si trova nella stessa transazione, in modo che l'utente non possa annullare la modifica senza perdere la modifica originale.

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.
}

Se si scrive un evento che aggiorna l'archivio:

  • Usare store.InUndoRedoOrRollback per evitare di apportare modifiche agli elementi del modello in Annulla. Il gestore delle transazioni imposta tutti gli elementi nell'archivio sullo stato originale.

  • Usare store.InSerializationTransaction per evitare di apportare modifiche durante il caricamento del modello dal file.

  • Le modifiche causeranno l'attivazione di altri eventi. Assicurarsi di evitare un ciclo infinito.

Tipi di evento store

Ogni tipo di evento corrisponde a una raccolta in Store.EventManagerDirectory. È possibile aggiungere o rimuovere gestori eventi in qualsiasi momento, ma è normale aggiungerli al caricamento del documento.

EventManagerDirectory Nome proprietà Esecuzione in caso di esecuzione
ElementAdded Viene creata un'istanza di una classe di dominio, una relazione di dominio, una forma, un connettore o un diagramma.
ElementDeleted Un elemento del modello è stato rimosso dalla directory degli elementi dell'archivio e non è più l'origine o la destinazione di alcuna relazione. L'elemento non viene effettivamente eliminato dalla memoria, ma viene conservato in caso di un futuro annullamento.
ElementEventsBegun Richiamato alla fine di una transazione esterna.
ElementEventsEnded Richiamato quando tutti gli altri eventi sono stati elaborati.
Elemento spostato Un elemento del modello è stato spostato da una partizione di archivio a un'altra.

Non è correlato alla posizione di una forma nel diagramma.
ElementPropertyChanged Il valore di una proprietà di dominio è stato modificato. Questa operazione viene eseguita solo se i valori precedenti e nuovi non sono uguali.
RolePlayerChanged Uno dei due ruoli (termina) di una relazione fa riferimento a un nuovo elemento.
RolePlayerOrderChanged In un ruolo con molteplicità maggiore di 1, la sequenza di collegamenti è cambiata.
TransactionBeginning
TransactionCommitted
TransactionRolledBack

Nota

Il componente Trasformazione modello di testo viene installato automaticamente come parte del carico di lavoro sviluppo di estensioni di Visual Studio. È anche possibile installarlo dalla scheda Singoli componenti di Programma di installazione di Visual Studio, nella categoria SDK, librerie e framework. Installare il componente Modeling SDK dalla scheda Singoli componenti .