Compartir a través de


Los controladores de eventos propagan cambios fuera del modelo

En el SDK de visualización y modelado, puede definir controladores de eventos del almacén para propagar los cambios a los recursos fuera del almacén, como variables de no-almacén, archivos, los modelos en otro almacenan, u otras extensiones de Visual Studio . Se ejecutan los controladores de eventos de almacén después del final de la transacción en la que el evento que desencadenaba. También se ejecutan en una operación de deshacer o de rehacer. Por consiguiente, a diferencia de reglas almacenadas, los eventos almacenados son más útiles para actualizar los valores que están fuera del almacén. A diferencia de los eventos de .NET, los controladores de eventos se registran almacenados para escuchar una clase: no tiene que registrar un controlador independiente para cada instancia. Para obtener más información sobre cómo elegir entre las diferentes maneras de controlar cambios, vea Responder a los cambios y propagarlos.

La superficie gráfica y otros controles de la interfaz de usuario son ejemplos de recursos externos que se pueden controlar por eventos almacenados.

Para definir un evento de almacén

  1. Elija el tipo de evento que desea controlar. Para obtener una lista completa, examine las propiedades de EventManagerDirectory. cada propiedad corresponde a un tipo de evento. La mayoría de los tipos de evento utilizados son:

    • ElementAdded – se desencadena cuando se crea un elemento, un vínculo de la relación, una forma o un conector modelo.

    • ElementPropertyChanged – se desencadena cuando el valor de una propiedad de dominio de Normal cambia. Se desencadena el evento si los valores nuevo y antiguo no son iguales. El evento no se puede aplicar a propiedades calculadas y personalizadas de almacenamiento.

      No se puede aplicar al rol de las propiedades que corresponden a los vínculos de la relación. En su lugar, utilice ElementAdded de controlar la relación del dominio.

    • ElementDeleted – desencadena una vez eliminado un elemento, una relación, una forma o un conector modelo. Todavía puede tener acceso a los valores de propiedad del elemento, pero no tendrá ninguna relación con otros elementos.

  2. Agregue una definición de clase parcial para TheDslDocData en un archivo de código independiente en el proyecto de DslPackage .

  3. Escriba el código de evento como un método, como en el ejemplo siguiente. Puede ser static, a menos que desee tener acceso a DocData.

  4. Reemplazo OnDocumentLoaded() para registrar el controlador. Si tiene más de un controlador, puede registrarlos todos en el mismo lugar.

La ubicación del código de registro no es esencial. DocView.LoadView() es una ubicación 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);
    }
  }

}

Mediante los eventos para realizar ajustes de Undoable en el almacén

Los eventos del almacén no se usan normalmente para propagar cambios dentro del almacén, porque el controlador de eventos se ejecuta después de que la transacción confirmada. En su lugar, se utilizaría una regla store. Para obtener más información, vea Las reglas propagan los cambios dentro del modelo.

Sin embargo, podría usar un controlador de eventos para realizar actualizaciones adicionales al almacén, si desea que el usuario pueda deshacer las actualizaciones adicionales independientemente del evento original. Por ejemplo, suponga que los caracteres en minúsculas son la convención habitual para los títulos del álbum. Puede escribir un controlador de eventos de almacén que corrige el título a minúsculas después de que el usuario la ha escrito en mayúscula. Pero el usuario puede utilizar el comando deshacer de cancelar la corrección, restablecer los caracteres en mayúsculas. Una segunda deshacer quitaría el cambio del usuario.

Por el contrario, si fuese una regla de almacén para lograr el mismo resultado, el cambio del usuario y la corrección estaría en la misma transacción, de modo que el usuario no puede deshacer el ajuste sin perder el cambio original.

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 escribe un evento que actualice el almacén:

  • Uso store.InUndoRedoOrRollback de evitar realizar cambios en los elementos del modelo en deshacer. El administrador de transacciones establecerá todo el almacén a su estado original.

  • Uso store.InSerializationTransaction de evitar modificaciones mientras el modelo se carga desde un archivo.

  • Los cambios provocarán otros eventos que se devolverán. Asegúrese de que se evite un bucle infinito.

Tipos de evento de almacén

cada tipo de evento corresponde a una colección en Store.EventManagerDirectory. Puede agregar o quitar controladores de eventos en cualquier momento, pero es habitual agregarlos cuando el documento se carga.

nombre de propiedad deEventManagerDirectory

Ejecutarse cuando

ElementAdded

Una instancia de una clase de dominio, de relación de dominio, de una forma, de un conector o diagrama se crea.

ElementDeleted

Un elemento del modelo se ha quitado del directorio del elemento del almacén y deja el origen o destino de cualquier relación. El elemento no se elimina realmente de memoria, pero se conserva en caso de una operación de deshacer futura.

ElementEventsBegun

Invocado al final de una transacción externa.

ElementEventsEnded

Invocado cuando se han procesado todos los demás eventos.

ElementMoved

Un elemento del modelo se ha movido desde una partición almacenada a otra.

Esto no está relacionado con la ubicación de una forma del diagrama.

ElementPropertyChanged

El valor de una propiedad de dominio ha cambiado. Se ejecuta sólo si los valores antiguos y nuevos son iguales.

RolePlayerChanged

Uno de los dos roles (extremos) de una relación hace referencia a un nuevo elemento.

RolePlayerOrderChanged

A un rol con multiplicidad es mayor que 1, la secuencia de vínculos ha cambiado.

TransactionBeginning

TransactionCommitted

TransactionRolledBack

Vea también

Otros recursos

Responder a los cambios y propagarlos

Código de ejemplo: esquemas circulares