Manipuladores de eventos propagam alterações fora do modelo
Na visualização e modelagem SDK, você pode definir manipuladores de eventos do armazenamento para propagar alterações para recursos fora do armazenamento, como, por exemplo, não armazenamento variáveis, arquivos, modelos em outros armazenamentos ou outros Visual Studio as extensões.Manipuladores de eventos do armazenamento são executados após o término da transação na qual ocorreu o evento de acionamento.Eles também são executados em uma operação de desfazer ou refazer.Portanto, ao contrário das regras de armazenamento, eventos de armazenamento são mais úteis para a atualização de valores que estão fora do armazenamento.Ao contrário.NET eventos, manipuladores de eventos do armazenamento são registrados para ouvir uma classe: você não precisa registrar um manipulador separado para cada instância.Para obter mais informações sobre como escolher entre diferentes maneiras de lidar com as alterações, consulte Respondendo a e propagação de alterações.
A superfície de gráfica e outros controles de interface de usuário são exemplos de recursos externos que podem ser tratados por eventos de armazenamento.
Para definir um evento de armazenamento
Escolha o tipo de evento que você deseja monitorar.Para obter uma lista completa, examine as propriedades de EventManagerDirectory.Cada propriedade corresponde a um tipo de evento.Mais freqüentemente usados são de tipos de eventos:
ElementAdded– disparado quando um elemento de modelo, link de relacionamento, forma ou o conector é criado.
ElementPropertyChanged – disparada quando o valor de um Normal a propriedade de domínio for alterada.O evento é disparado somente se os valores novos e antigos não são iguais.O evento não pode ser aplicado às propriedades de armazenamento personalizada e calculado.
Ele não pode ser aplicado às propriedades de função que correspondem aos links de relacionamento.Em vez disso, use ElementAdded para monitorar a relação de domínio.
ElementDeleted– disparado depois de um elemento de modelo, relacionamento, conector ou forma foi excluído.Você ainda pode acessar os valores de propriedade do elemento, mas terá sem relações com outros elementos.
Adicionar uma definição de classe parcial para YourDslDocData em um arquivo de código separados na DslPackage project.
Escreva o código do evento como um método, como no exemplo a seguir.Ele pode ser static, a menos que você deseja acessar DocData.
Substituir OnDocumentLoaded() para registrar o manipulador.Se você tiver mais de um manipulador, você pode registrá-los todos no mesmo lugar.
O local do código de registro não é crítico.DocView.LoadView()é um local alternativo.
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);
}
}
}
Usando eventos para fazer os ajustes podem ser desfeitas no armazenamento
Eventos de armazenamento não são normalmente usados para propagar as alterações dentro do armazenamento, como o manipulador de eventos é executado depois que a transação é confirmada.Em vez disso, você usaria uma regra de armazenamento.Para obter mais informações, consulte Regras de propagam alterações dentro do modelo.
No entanto, você poderia usar um manipulador de eventos para fazer atualizações adicionais para o armazenamento, se desejar que o usuário seja capaz de desfazer as atualizações adicionais separadamente a partir do evento original.Por exemplo, suponha que caracteres minúsculos são da convenção utilizada para títulos de álbum.Você poderia escrever um manipulador de eventos de armazenamento que corrige o título para minúsculas depois que o usuário tiver digitado em letras maiúsculas.Mas o usuário poderia usar o comando Desfazer para cancelar a correção, restaurando os caracteres em maiúsculas.Um segundo desfazer removeria a alteração do usuário.
Por outro lado, se você escreveu uma regra de armazenamento para fazer a mesma coisa, a alteração do usuário e sua correção seria na mesma transação, para que o usuário não pôde desfazer o ajuste sem perder a alteração 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.
}
Se você gravar um evento que atualiza o armazenamento:
Use store.InUndoRedoOrRollback para evitar fazer alterações em elementos de modelo em Desfazer.O Gerenciador de transações definirá tudo no armazenamento de volta ao seu estado original.
Use store.InSerializationTransaction para evitar fazer alterações enquanto o modelo está sendo carregado a partir do arquivo.
Suas alterações fará com que mais eventos ser disparado.Certifique-se de que você evite um loop infinito.
Tipos de eventos de armazenamento
Cada tipo de evento corresponde a uma coleção em Store.EventManagerDirectory.Você pode adicionar ou remover manipuladores de eventos a qualquer momento, mas é usual para adicioná-los quando o documento é carregado.
EventManagerDirectoryNome da propriedade |
Executado quando |
---|---|
ElementAdded |
Uma instância de uma classe de domínio, uma relação de domínio, forma, conector ou diagrama é criada. |
ElementDeleted |
Um elemento de modelo foi removido do diretório do elemento da loja e não está mais na origem ou destino de qualquer relação.O elemento não é realmente apagado da memória, mas é retido no caso de uma futura desfazer. |
ElementEventsBegun |
Invocado no final de uma transação externa. |
ElementEventsEnded |
Chamado quando todos os outros eventos foram processados. |
ElementMoved |
Um elemento de modelo foi movido de um armazenamento partição para outra. Isso não está relacionado ao local de uma forma no diagrama. |
ElementPropertyChanged |
O valor de uma propriedade de domínio foi alterado.Isso é executado somente se os valores novos e antigos são diferentes. |
RolePlayerChanged |
Uma das duas funções (termina) de um relacionamento faz referência a um novo elemento. |
RolePlayerOrderChanged |
Em uma função com multiplicidade maior que 1, a seqüência de links foi alterada. |
TransactionBeginning |
|
TransactionCommitted |
|
TransactionRolledBack |