Obslužné rutiny události šíří změny mimo model

Ve Vizualizační a modelovací sadě SDK můžete definovat obslužné rutiny událostí pro šíření změn do prostředků mimo úložiště, jako jsou proměnné, soubory, modely v jiných úložištích nebo jiná rozšíření sady Visual Studio. Obslužné rutiny událostí úložiště se spouští po konci transakce, ve které došlo k aktivační události. Provádí se také v operaci Zpět nebo Znovu. Na rozdíl od pravidel úložiště jsou proto události úložiště nejužitečnější pro aktualizaci hodnot mimo úložiště. Na rozdíl od událostí rozhraní .NET jsou obslužné rutiny událostí úložiště registrovány k naslouchání třídě: pro každou instanci nemusíte registrovat samostatnou obslužnou rutinu. Další informace o tom, jak si vybrat mezi různými způsoby zpracování změn, naleznete v tématu Reagování na změny a šíření změn.

Grafický povrch a další ovládací prvky uživatelského rozhraní jsou příklady externích prostředků, které je možné zpracovat událostmi úložiště.

Definování události úložiště

  1. Zvolte typ události, kterou chcete monitorovat. Úplný seznam najdete ve vlastnostech souboru EventManagerDirectory. Každá vlastnost odpovídá typu události. Nejčastěji používané typy událostí jsou:

    • ElementAdded – aktivuje se při vytvoření prvku modelu, vazby relace, obrazce nebo spojnice.

    • ElementPropertyChanged – aktivuje se při změně hodnoty Normal vlastnosti domény. Událost se aktivuje pouze v případě, že nové a staré hodnoty nejsou stejné. Událost nelze použít pro počítané a vlastní vlastnosti úložiště.

      Nelze jej použít u vlastností role, které odpovídají propojením relací. Místo toho použijte ElementAdded k monitorování vztahu domény.

    • ElementDeleted – aktivuje se po odstranění prvku modelu, relace, tvaru nebo spojnice. Stále můžete přistupovat k hodnotám vlastnosti elementu, ale nebude mít žádné relace s jinými prvky.

  2. Přidejte částečnou definici třídy pro YourDslDocData do samostatného souboru kódu v projektu DslPackage.

  3. Napište kód události jako metodu, jako v následujícím příkladu. Může to být static, pokud nechcete mít přístup DocData.

  4. Přepsání OnDocumentLoaded() pro registraci obslužné rutiny Pokud máte více než jednu obslužnou rutinu, můžete je všechny zaregistrovat na stejném místě.

Umístění registračního kódu není důležité. DocView.LoadView() je alternativní umístění.

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

Použití událostí k vrácení zpětných úprav v úložišti

Události úložiště se obvykle nepoužívají k šíření změn v úložišti, protože obslužná rutina události se spustí po potvrzení transakce. Místo toho byste použili pravidlo úložiště. Další informace naleznete v tématu Pravidla šíření změn v rámci modelu.

Obslužnou rutinu události však můžete použít k provedení dalších aktualizací v úložišti, pokud chcete, aby uživatel mohl vrátit další aktualizace zpět odděleně od původní události. Předpokládejme například, že u názvů alb jsou obvyklé konvence malých písmen. Můžete napsat obslužnou rutinu události úložiště, která opraví název na malá písmena poté, co ho uživatel zadá velkými písmeny. Uživatel ale může k zrušení opravy použít příkaz Zpět a obnovit velká písmena. Druhé vrácení zpět by odebralo změnu uživatele.

Pokud jste naopak napsali pravidlo obchodu, které by udělalo totéž, změna uživatele a vaše oprava by byly ve stejné transakci, takže uživatel nemohl vrátit zpět úpravu bez ztráty původní změny.

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

Pokud napíšete událost, která aktualizuje úložiště:

  • Slouží store.InUndoRedoOrRollback k tomu, abyste se vyhnuli změnám prvků modelu v příkazu Zpět. Správce transakcí nastaví všechno v úložišti zpět do původního stavu.

  • Slouží store.InSerializationTransaction k zabránění provádění změn při načítání modelu ze souboru.

  • Vaše změny způsobí, že se aktivují další události. Ujistěte se, že se vyhnete nekonečné smyčce.

Ukládání typů událostí

Každý typ události odpovídá kolekci v Store.EventManagerDirectory. Obslužné rutiny událostí můžete kdykoli přidat nebo odebrat, ale při načtení dokumentu je obvykle přidáte.

EventManagerDirectory Název vlastnosti Spuštěno při
ElementAdded Vytvoří se instance doménové třídy, vztahu domény, obrazce, spojnice nebo diagramu.
ElementDeleted Prvek modelu byl odebrán z adresáře elementů úložiště a již není zdrojem ani cílem žádné relace. Prvek není ve skutečnosti odstraněn z paměti, ale je zachován v případě budoucí vrácení zpět.
ElementEventsBegun Vyvolána na konci vnější transakce.
ElementEventsEnded Vyvoláno při zpracování všech ostatních událostí.
ElementMoved Prvek modelu byl přesunut z jednoho oddílu úložiště do jiného.

To nesouvisí s umístěním obrazce v diagramu.
ElementPropertyChanged Hodnota vlastnosti domény se změnila. To se provede pouze v případě, že staré a nové hodnoty nejsou stejné.
RolePlayerChanged Jedna ze dvou rolí (končí) relace odkazuje na nový prvek.
RolePlayerOrderChanged V roli s násobností větší než 1 se posloupnost propojení změnila.
TransactionBeginning
TransactionCommitted
TransactionRolledBack

Poznámka:

Komponenta Transformace textové šablony se automaticky nainstaluje jako součást sady funkcí vývoje rozšíření sady Visual Studio. Můžete ho také nainstalovat z karty Jednotlivé komponenty Instalační program pro Visual Studio v kategorii sad SDK, knihoven a architektur. Nainstalujte komponentu Modeling SDK z karty Jednotlivé komponenty .