共用方式為


事件處理常式傳播模型外的變更

在視覺化和模型的 SDK 中,您可以定義儲存區事件處理常式來將變更傳播到外部存放區中,例如非存放區的變數、 檔案、 模型中其他儲存區,或其他資源Visual Studio副檔名。 儲存區事件處理常式會執行結束之後,觸發的事件發生的交易。 它們也會執行復原或取消復原作業中。 因此,和儲存庫規則存放區事件是最適合用來更新存放區之外的值。 不像。NET 事件,儲存區事件處理常式已註冊接聽類別: 您不需要登錄個別的處理常式,每個執行個體。 如需有關如何選擇不同的方式來處理變更的詳細資訊,請參閱回應及傳播變更

圖形化的介面和其他使用者介面控制項都可由儲存區事件處理的外部資源的範例。

若要定義儲存區事件

  1. 請選擇您想要監視的事件的型別。 如需完整清單,查看內容的EventManagerDirectory。 每個屬性會對應到事件型別。 最常使用的事件類型:

    • ElementAdded– 當模型項目時,就會觸發,關聯性連結、 圖形或連接器會建立。

    • ElementPropertyChanged – 觸發的時機的值Normal網域屬性變更時。 在新的和舊的值不相等時,才會觸發事件。 事件無法用在計算和自訂的存放裝置內容。

      它不能套用到角色屬性對應至關聯性連結。 相反地,使用ElementAdded來監視網域關聯性。

    • ElementDeleted-觸發模型項目之後,關聯性、 圖形或連接器已被刪除。 您仍然可以存取的屬性值的項目,但有其他項目沒有關聯性。

  2. 加入部分類別定義的 YourDslDocData中的個別程式碼檔案DslPackage專案。

  3. 寫入事件的程式碼,作為一種方法,如下例所示。 它可以是static,除非您想要存取DocData。

  4. 覆寫OnDocumentLoaded()註冊處理常式。 如果您有一個以上的處理常式時,您可以維持在相同的位置來註冊它們。

註冊程式碼的位置並不重要的。 DocView.LoadView()是替代的位置。

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

}

若要復原的調整存放區中使用事件

儲存區事件不會正常用於傳播變更內部存放區中,因為事件處理常式執行後就會認可交易。 相反地,您會使用存放區的規則。 如需詳細資訊,請參閱 規則傳播模型內的變更

不過,您可以使用事件處理常式存放區中,建立其他的更新,如果您希望使用者能夠復原其他的更新與原始的事件分開。 例如,假設小寫字元是常見的慣例專輯標題。 您可以撰寫用來解決這個標題以小寫字母之後使用者輸入其以大寫, 儲存區事件處理常式。 但是,使用者無法使用 [復原] 指令,來取消您的更正,還原大寫字元。 第二個復原會移除使用者的變更。

相較之下,撰寫執行相同動作時,某規則存放區時,使用者的變更與您的更正總是處於相同的交易,讓使用者無法復原調整] 而不會遺失原始的變更。

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

如果您撰寫的事件,就會更新存放區:

  • 使用store.InUndoRedoOrRollback ,請勿變更中復原的模型項目。 交易管理員會設定回其原始狀態存放區中所有項目。

  • 使用store.InSerializationTransaction ,以免時從檔案載入模型進行變更。

  • 您的變更會導致進一步的事件會觸發。 請確定您避免發生無限迴圈。

儲存事件型別

每一種事件類型會對應到在 Store.EventManagerDirectory 中的集合。 您可以新增或移除事件處理常式在任何時間,但通常會在載入文件時,請將它們。

EventManagerDirectory屬性名稱

執行時機

ElementAdded

網域類別、 網域關係、 圖形、 連接器或圖表的被建立執行個體。

ElementDeleted

模型項目已從儲存區的項目目錄中移除且不再來源或目標的任何關聯。 項目確實地刪除從記憶體中,但會保留在未來的復原的情況下。

ElementEventsBegun

叫用外部交易的結尾。

ElementEventsEnded

當在處理完所有其他事件叫用。

ElementMoved

模型項目已從一個儲存區的磁碟分割移到另一個。

這被無關的圖表上的圖案位置。

ElementPropertyChanged

網域屬性的值已經變更。 這是在新舊值相等時,才執行。

RolePlayerChanged

兩個角色之一 (結束) 的關聯性會參考新的項目。

RolePlayerOrderChanged

在角色中的重數大於 1,已變更的連結順序。

TransactionBeginning

TransactionCommitted

TransactionRolledBack

請參閱

其他資源

回應及傳播變更

範例程式碼: 電路圖表