Manipuladores de eventos propagam alterações fora do modeloEvent Handlers Propagate Changes Outside the Model

No SDK de visualização e modelagem, você pode definir manipuladores de eventos de armazenamento para propagar alterações para recursos fora da loja, como variáveis de não armazenamento, arquivos, modelos em outras lojas ou outras extensões do Visual Studio.In Visualization and Modeling SDK, you can define store event handlers to propagate changes to resources outside the store, such as non-store variables, files, models in other stores, or other Visual Studio extensions. Os manipuladores de eventos de armazenamento são executados após o término da transação na qual o evento de disparo ocorreu.Store event handlers are executed after the end of the transaction in which the triggering event occurred. Eles também são executados em uma operação de desfazer ou refazer.They are also executed in an Undo or Redo operation. Portanto, ao contrário das regras de armazenamento, os eventos de armazenamento são mais úteis para atualizar os valores que estão fora do repositório.Therefore, unlike store rules, store events are most useful for updating values that are outside the store. Ao contrário dos eventos do .NET, os manipuladores de eventos de armazenamento são registrados para escutar uma classe: você não precisa registrar um manipulador separado para cada instância.Unlike .NET events, store event handlers are registered to listen to a class: you do not have to register a separate handler for each instance. Para obter mais informações sobre como escolher entre diferentes maneiras de lidar com alterações, consulte respondendo e propagando alterações.For more information about how to choose between different ways to handle changes, see Responding to and Propagating Changes.

A superfície gráfica e outros controles de interface do usuário são exemplos de recursos externos que podem ser tratados por eventos de armazenamento.The graphical surface and other user interface controls are examples of external resources that can be handled by store events.

Para definir um evento de repositórioTo define a store event

  1. Escolha o tipo de evento que você deseja monitorar.Choose the type of event that you want to monitor. Para obter uma lista completa, examine as propriedades de EventManagerDirectory .For a full list, look at the properties of EventManagerDirectory. Cada propriedade corresponde a um tipo de evento.Each property corresponds to a type of event. Os tipos de evento usados com mais frequência são:The most frequently used event types are:

    • ElementAdded -disparado quando um elemento de modelo, link de relação, forma ou conector é criado.ElementAdded - triggered when a model element, relationship link, shape or connector is created.

    • ElementPropertyChanged-disparado quando o valor de uma Normal propriedade de domínio é alterado.ElementPropertyChanged - triggered when the value of a Normal domain property is changed. O evento será disparado somente se os valores novos e antigos não forem iguais.The event is triggered only if the new and old values are not equal. O evento não pode ser aplicado a propriedades de armazenamento calculadas e personalizadas.The event cannot be applied to calculated and custom storage properties.

      Ele não pode ser aplicado às propriedades de função que correspondem aos links de relação.It cannot be applied to the role properties that correspond to relationship links. Em vez disso, use ElementAdded para monitorar a relação de domínio.Instead, use ElementAdded to monitor the domain relationship.

    • ElementDeleted -disparado depois que um elemento de modelo, relação, forma ou conector foi excluído.ElementDeleted - triggered after a model element, relationship, shape or connector has been deleted. Você ainda pode acessar os valores de Propriedade do elemento, mas ele não terá nenhuma relação com outros elementos.You can still access the property values of the element, but it will have no relationships to other elements.

  2. Adicione uma definição de classe parcial para YourDslDocData em um arquivo de código separado no projeto DslPackage .Add a partial class definition for YourDslDocData in a separate code file in the DslPackage project.

  3. Escreva o código do evento como um método, como no exemplo a seguir.Write the code of the event as a method, as in the following example. Pode ser static , a menos que você queira acessar DocData .It can be static, unless you want to access DocData.

  4. Substituir OnDocumentLoaded() para registrar o manipulador.Override OnDocumentLoaded() to register the handler. Se você tiver mais de um manipulador, poderá registrá-los todos no mesmo local.If you have more than one handler, you can register them all in the same place.

O local do código de registro não é crítico.The location of the registration code is not critical. DocView.LoadView() é um local alternativo.DocView.LoadView() is an alternative location.

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

Usar eventos para fazer ajustes desfeitos na lojaUse Events to Make Undoable Adjustments in the Store

Os eventos de armazenamento normalmente não são usados para propagar alterações no repositório, pois o manipulador de eventos é executado depois que a transação é confirmada.Store events are not normally used for propagating changes inside the store, because the event handler executes after the transaction is committed. Em vez disso, você usaria uma regra de armazenamento.Instead, you would use a store rule. Para obter mais informações, consulte regras propagar alterações no modelo.For more information, see Rules Propagate Changes Within the Model.

No entanto, você pode usar um manipulador de eventos para fazer atualizações adicionais na loja, se quiser que o usuário consiga desfazer as atualizações adicionais separadamente do evento original.However, you could use an event handler to make additional updates to the store, if you want the user to be able to undo the additional updates separately from the original event. Por exemplo, suponha que caracteres minúsculos sejam a Convenção comum para títulos de álbuns.For example, suppose that lower case characters are the usual convention for album titles. Você poderia escrever um manipulador de eventos de armazenamento que corrija o título para letras minúsculas depois que o usuário o tiver digitado em letras maiúsculas.You could write a store event handler that corrects the title to lower case after the user has typed it in upper case. Mas o usuário pode usar o comando Desfazer para cancelar a correção, restaurando os caracteres em maiúsculas.But the user could use the Undo command to cancel your correction, restoring the upper case characters. Uma segunda desfazer removeria a alteração do usuário.A second Undo would remove the user's change.

Por outro lado, se você escreveu uma regra de repositório para fazer a mesma coisa, a alteração do usuário e sua correção estarão na mesma transação, para que o usuário não possa desfazer o ajuste sem perder a alteração original.By contrast, if you wrote a store rule to do the same thing, the user's change and your correction would be in the same transaction, so that the user could not undo the adjustment without losing the original change.

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 você escrever um evento que atualize o repositório:If you write an event that updates the store:

  • Use store.InUndoRedoOrRollback para evitar fazer alterações em elementos de modelo em desfazer.Use store.InUndoRedoOrRollback to avoid making changes to model elements in Undo. O Gerenciador de transações definirá tudo no repositório de volta para seu estado original.The transaction manager will set everything in the store back to its original state.

  • Use store.InSerializationTransaction para evitar fazer alterações enquanto o modelo está sendo carregado do arquivo.Use store.InSerializationTransaction to avoid making changes while the model is being loaded from file.

  • Suas alterações farão com que outros eventos sejam disparados.Your changes will cause further events to be triggered. Certifique-se de evitar um loop infinito.Make sure that you avoid an infinite loop.

Armazenar tipos de eventoStore Event types

Cada tipo de evento corresponde a uma coleção em Store. EventManagerDirectory.Each event type corresponds to a collection in Store.EventManagerDirectory. Você pode adicionar ou remover manipuladores de eventos a qualquer momento, mas é comum adicioná-los quando o documento é carregado.You can add or remove event handlers at any time, but it is usual to add them when the document is loaded.

EventManagerDirectory Nome da propriedadeEventManagerDirectory Property name Executado quandoExecuted when
ElementAddedElementAdded Uma instância de uma classe de domínio, relação de domínio, forma, conector ou diagrama é criada.An instance of a domain class, domain relationship, shape, connector or diagram is created.
ElementDeletedElementDeleted Um elemento de modelo foi removido do diretório de elementos do repositório e não é mais a origem ou o destino de nenhuma relação.A model element has been removed from the store's element directory and is no longer the source or target of any relationship. O elemento não é realmente excluído da memória, mas é retido no caso de um futuro desfazer.The element is not actually deleted from memory, but is retained in case of a future Undo.
ElementEventsBegunElementEventsBegun Chamado no final de uma transação externa.Invoked at the end of an outer transaction.
ElementEventsEndedElementEventsEnded Chamado quando todos os outros eventos foram processados.Invoked when all other events have been processed.
ElementMovedElementMoved Um elemento de modelo foi movido de uma partição de repositório para outra.A model element has been moved from one store partition to another.

Isso não está relacionado ao local de uma forma no diagrama.This is not related to the location of a shape on the diagram.
ElementPropertyChangedElementPropertyChanged O valor de uma propriedade de domínio foi alterado.The value of a domain property has changed. Isso será executado somente se os valores antigo e novo forem desiguais.This is executed only if the old and new values are unequal.
RolePlayerChangedRolePlayerChanged Uma das duas funções (extremidades) de uma relação faz referência a um novo elemento.One of the two roles (ends) of a relationship references a new element.
RolePlayerOrderChangedRolePlayerOrderChanged Em uma função com multiplicidade maior que 1, a sequência de links foi alterada.In a role with multiplicity greater than 1, the sequence of links has changed.
TransactionBeginningTransactionBeginning
TransactionCommittedTransactionCommitted
TransactionRolledBackTransactionRolledBack

Confira tambémSee also

Observação

O componente de transformação de modelo de texto é instalado automaticamente como parte da carga de trabalho de desenvolvimento de extensão do Visual Studio .The Text Template Transformation component is automatically installed as part of the Visual Studio extension development workload. Você também pode instalá-lo na guia componentes individuais do instalador do Visual Studio, na categoria SDKs, bibliotecas e estruturas .You can also install it from the Individual components tab of Visual Studio Installer, under the SDKs, libraries, and frameworks category. Instale o componente SDK de modelagem da guia componentes individuais .Install the Modeling SDK component from the Individual components tab.