イベント ハンドラーによって変更内容がモデル外に反映される
Visualization and Modeling SDK でまたはを Visual Studio の他の拡張子のない他のストアを格納する変数ファイルなどモデル ストアの外部のリソースへの変更を反映するためにストアのイベント ハンドラーを定義します。ストアのイベント ハンドラーはイベントが発生したトランザクションが終了した後で実行されます。これらは元の実行または操作をやり直してから/LTCG。したがってストアの規則とは異なりストア内のイベントがストアの外部にある値を更新する場合に最も役立ちます。.NET イベントとは異なりストア内のイベント ハンドラーはクラスをリッスンするように登録されます : インスタンスごとに異なるハンドラーを登録する必要はありません。変更を処理するさまざまな方法を選択する方法の詳細については変更内容への対応および変更内容の反映 を参照してください。
グラフィカルな面などのユーザー インターフェイス コントロールがストアのイベントで処理できる外部リソースの例です。
ストアのイベントを定義するには
監視対象とするイベントの種類を選択します。一覧についてはEventManagerDirectory のプロパティを参照してください。各プロパティにはイベントの型に対応します。最もよく使用されるイベントの種類は次のとおりです :
トリガーされる ElementAdded –モデル要素関係のリンクシェイプまたはコネクタが作成されます。
トリガーされる ElementPropertyChanged – Normal ドメインのプロパティの値が変更されます。イベントは新しいや古い値が等しくない場合にのみ発生します。イベントでは計算されたカスタム ストレージのプロパティに適用できません。
これはリレーションシップのリンクに対応するロールのプロパティに適用できません。代わりにドメイン リレーションシップを監視するに ElementAdded を使用します。
トリガーされる ElementDeleted –モデル要素関係シェイプまたはコネクタを削除した後。その要素のプロパティ値にアクセスできます他の要素との関係はありません。
DslPackage プロジェクトの個別のコード ファイルの YourDslDocData の部分クラス定義を追加します。
次の例のようにメソッドとしてイベントのコードを記述します。これは DocData にアクセスするには static です。
ハンドラーを登録するためにオーバーライド 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);
}
}
}
ストアの Undoable 調整するイベントを使用する
ストアのイベントはストア内の変更を反映するためにトランザクションがコミットされた後イベント ハンドラーが実行されるため使用できません。代わりにストアの規則を使用します。詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
ユーザーが更新を追加元のイベントを個別に元に戻せれば場合はストアに追加更新を行うにはイベント ハンドラーを使用できます。たとえば小文字がアルバムのタイトルの通常の規則があるとします。ユーザーが大文字で入力すると小文字のタイトルを修正するストアのイベント ハンドラーを作成できます。ただしユーザーは大文字を復元する変更をキャンセルに戻す] コマンドを使用できます。第 2 にユーザーの変更を削除します。
これに対して同じ操作を格納する規則を作成する場合ユーザーの変更が同じトランザクションと変更はユーザーがソースの変更が失われます変更を元に戻すことができるのはあるからです。
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 |
モデル要素は 1 個のストア パーティションから別のページに移動されました。 これはダイアグラムの図形の位置とは関係ありません。 |
ElementPropertyChanged |
ドメインのプロパティの値が変更されました。これは新旧の値が等しくない場合にだけ実行されます。 |
RolePlayerChanged |
リレーションシップの 2 個のロール (エッジ) の 1 つが新しい要素を参照します。 |
RolePlayerOrderChanged |
超える多重度のロールでは1 個リンクのシーケンス変更されています。 |
TransactionBeginning |
|
TransactionCommitted |
|
TransactionRolledBack |