方法: UML モデル内で変更に応答する
更新 : 2011 年 3 月
Visual Studio の UML モデルで変更が生じたときに実行されるコードを作成できます。 このコードは、ユーザーが直接行った変更にも、他の Visual Studio 拡張機能による変更にも同様に応答します。
ヒント
この機能は UML 拡張 API では直接サポートされていません。 したがって、やや独創的な技術を使用する必要があります。 必要なコードはこのトピックに含まれています。 ただし、場合によっては予測不可能な影響が及ぶことがあります。 UML の Visual Studio 実装の今後の変更によって、このトピックで説明する技術が無効になることも考えられます。
このトピックで説明する技術を使用するにあたって、UML ツールの実装に使用される、視覚化およびモデリング SDK (VMSDK) について理解しておくことをお勧めします。 詳細については、「Visualization and Modeling SDK - ドメイン固有言語」を参照してください。
このトピックの内容
UML 拡張プロジェクトの作成
イベントと規則
イベントの定義
例: イベントを使用した、ステレオタイプからのクラスの色分け
規則の定義
例: 規則を使用した、ステレオタイプからのクラスの色分け
例: 既定では双方向の関連
コア モデルとビュー モデル
UML 拡張プロジェクトの作成
多くの場合は、コマンド ハンドラーまたはジェスチャ ハンドラーを既に実装している拡張機能にイベント ハンドラーを追加します。 その場合は、ここで説明するコードを同じ Visual Studio プロジェクトに追加できます。 詳細については、「方法: モデリング図にメニュー コマンドを定義する」および「方法: モデリング図にドロップおよびダブルクリック ハンドラーを定義する」を参照してください。
個別の Visual Studio 拡張機能にイベント ハンドラーを作成する場合は、新しい UML 検証プロジェクトをまず作成します。 [新しいプロジェクト] ダイアログ ボックスで [モデリング プロジェクト] をクリックし、[Model Validation Extension] (モデル検証拡張機能) を選択します。 または、「方法: UML モデルの検証制約を定義する」の手順「検証拡張機能の定義」に従うこともできます。
以下の参照をプロジェクトに追加する必要があります。
\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.Uml.dll
Microsoft.VisualStudio.ArchitectureTools.Extensibility.dll
Microsoft.VisualStudio.Modeling.Sdk.10.0dll
Microsoft.VisualStudio.Modeling.Sdk.Diagrams.10.0.dll
Microsoft.VisualStudio.Uml.Interfaces.dll
イベントと規則
VMSDK には、ストア内の変更を検出するために 2 つの主要な方法が用意されています。
イベント ハンドラーは、変更が発生したトランザクションが終了した後で変更に応答します。 イベント ハンドラーは、モデルの外部の変更をユーザー インターフェイス、ファイル、またはデータベースに反映させるために通常使用されます。 新しいトランザクションでモデルをさらに変更するイベント ハンドラーを作成することもできます。
規則は、変更が発生したトランザクション内で変更に応答します。 通常、規則はモデル内の変更を反映させるために使用されるので、モデルの 2 つの部分間で一貫性が保たれます。 トランザクションを取り消すことで無効な変更を防ぐ規則を作成することもできます。
トランザクションの詳細については、「方法: トランザクションを使用してモデルの更新をリンクする」を参照してください。
イベント ハンドラーの定義
変更が発生したときにイベント ハンドラーが呼び出されるようにするには、イベント ハンドラーを登録する必要があります。 ハンドラーは、UseCase やアクティビティなど、監視する要素のクラスごとに登録する必要があります。 インスタンスごとに登録する必要はありません。
以下の例では、ユーザーが適用するステレオタイプに従って UML クラスの色を設定します。 イベント ハンドラーは、ステレオタイプのインスタンスが作成されるか、削除されたときにトリガーされるように登録されます。 この例では規則ではなくイベント ハンドラーを使用するので、ハンドラーはステレオタイプが変更されるトランザクションの完了後に呼び出されます。 色は VMSDK ストアの変更でもあるので、2 回目のトランザクションで実行する必要があります。
イベント ハンドラーを使用して、ストアの外部で変更を行うこともできます。
以下の例のコードを使用すると、選択したイベントに応答できます。 このコードに関する重要な注意点は次のとおりです。
イベント ハンドラーを登録するために検証 API が使用されます。 検証フレームワークは、モデルが開かれたときにコードを実行する便利な手段をもたらします。 ただし、コードで実際に検証が行われるわけではなく、更新のためにユーザーが検証を呼び出す必要はありません。
イベント ハンドラーは、Store.EventManagerDirectory に追加されるメソッドです。 これは UML ModelStore ではなく、基になる VMSDK (DSL) の実装の Store です。 EventManagerDirectory には、ElementAdded や ElementDeleted などの、イベントの各種類に対応した固定の辞書のセットが含まれています。
イベントを登録するには、監視する実装クラスまたは関係の名前を把握しておく必要があります。 これらのクラスは Microsoft.VisualStudio.Modeling.Uml.dll で定義されます。クラス名はデバッガーでプロパティを確認するときに表示されます。 これらのクラス メンバーは、IClass、IStereotype などの適切なインターフェイスの種類にキャストできます。 インターフェイスの種類の一覧については、「モデル要素の型」を参照してください。
実装クラス名は、今後のリリースでは異なる場合があります。
イベント ハンドラーは、ユーザーが [元に戻す] コマンドや [やり直し] コマンドを呼び出したときに呼び出されます。 たとえば、Add イベントの後には [元に戻す] コマンドによって Delete イベントが発生します。 イベント ハンドラーがストアの外部での変更を反映させる場合は、これらのイベントに応答する必要があります。 ただし、[元に戻す] または [やり直し] に応答してストア内で変更を行ったり、モデルがファイルから読み取られるときに変更を行ったりしないようにします。 if (!store.InUndoRedoOrRollback && !store.InSerializationTransaction)... を使用できます。
ここに示す例では、モデル内でオブジェクトを追加および削除するためのイベント ハンドラーを示しています。 プロパティ値を変更するためのイベント ハンドラーを作成することもできます。 詳細については、「イベント ハンドラーによって変更内容がモデル外に反映される」を参照してください。
イベントの詳細については、「イベント ハンドラーによって変更内容がモデル外に反映される」を参照してください。
例: イベントを使用した、ステレオタイプによるクラスの色分け
この例では、System.Drawing.dll へのプロジェクト参照を追加する必要もあります。
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Drawing;
using System.Linq;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Validation;
using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.Uml.Profiles;
using Microsoft.VisualStudio.Uml.UseCases;
using Microsoft.VisualStudio.Uml.ModelStore; // in private assembly. Used for Get|IsElementDefinition()
namespace UmlEvents // <<<< EDIT
{
/// <summary>
/// Wraps a UML model to add stereotype coloring.
/// </summary>
public partial class ColoringModelAdapter
{
// This is the underlying DSL store, not the wrapping UML ModelStore:
private Store store;
/// <summary>
/// This isn't actually validation. It's to couple this adapter to the model before we start.
/// The validation package creates an instance of this class and then calls this method.
/// See "Validation": https://msdn.microsoft.com/library/bb126413.aspx
/// </summary>
/// <param name="vcontext"></param>
/// <param name="model"></param>
[Export(typeof(System.Action<ValidationContext, object>))]
[ValidationMethod(ValidationCategories.Open)]
public void ConnectAdapterToModel(ValidationContext vcontext, IModel model)
{
// This is the underlying DSL store, not the wrapping UML ModelStore:
store = (model as ModelElement).Store;
// Add an event that triggers on creating a stereotype instance.
// See "Event handlers": https://msdn.microsoft.com/library/bb126250.aspx
DomainClassInfo siClass = store.DomainDataDirectory.FindDomainClass
("Microsoft.VisualStudio.Uml.Classes.StereotypeInstance");
store.EventManagerDirectory.ElementAdded.Add(siClass,
new EventHandler<ElementAddedEventArgs>(StereotypeInstanceAdded));
// For the deletion, we need to trigger from the deleted link
// between the stereotype instance and the model element -
// because after deletion we can't find the element from the stereotype instance.
DomainRelationshipInfo linkToStereotypeClass = store.DomainDataDirectory.FindDomainRelationship
("Microsoft.VisualStudio.Uml.Classes.ElementHasAppliedStereotypeInstances");
store.EventManagerDirectory.ElementDeleted.Add(linkToStereotypeClass,
new EventHandler<ElementDeletedEventArgs>(StereotypeInstanceDeleted));
// Add here handlers for other events.
}
/// <summary>
/// Event handler called whenever a stereotype instance is linked to a uml model element.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StereotypeInstanceAdded(object sender, ElementAddedEventArgs e)
{
// Don't handle changes in undo or load from file:
if (store.InUndoRedoOrRollback || store.InSerializationTransaction) return;
IStereotypeInstance si = e.ModelElement as IStereotypeInstance;
IElement umlElement = si.Element;
// Work only with the core model, not the views:
if (!umlElement.IsElementDefinition()) return;
// I'm only interested in coloring classes and interfaces:
if (!(umlElement is IType)) return;
Color? color = ColorForStereotype(si.Name);
if (color.HasValue)
{
SetColorOfShapes(si.Element, color.Value);
}
}
/// <summary>
/// Called whenever a stereotype instance is deleted - well, actually,
/// when the link between the stereotype instance and the uml model element is deleted.
/// Triggering on the link deletion allows us to get both ends.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StereotypeInstanceDeleted(object sender, ElementDeletedEventArgs e)
{
// Don't handle changes in undo or load from file:
if (store.InUndoRedoOrRollback || store.InSerializationTransaction) return;
// Use the generic link type to avoid unearthing the UML implementation DLL:
ElementLink elementToStereotypeLink = e.ModelElement as ElementLink;
IElement umlElement = elementToStereotypeLink.LinkedElements[0] as IElement;
IStereotypeInstance si = elementToStereotypeLink.LinkedElements[1] as IStereotypeInstance;
// Work only with the core model, not the views:
if (!umlElement.IsElementDefinition()) return;
// We're here either because a stereotype is being un-applied,
// or because the uml element is being deleted.
// Don't bother if the element is being deleted:
if ((umlElement as ModelElement).IsDeleting) return;
// We're only interested in classes and interfaces:
if (!(umlElement is IType)) return;
// Because more than one stereotype can be applied to an element,
// we should check to see if there are any remaining:
Color newColor = Color.WhiteSmoke; // Default if there aren't.
foreach (IStereotypeInstance remainingSi in umlElement.AppliedStereotypes)
{
Color? color = ColorForStereotype(remainingSi.Name);
if (color.HasValue)
{
newColor = color.Value;
break;
}
}
SetColorOfShapes(umlElement, newColor);
}
private void SetColorOfShapes(IElement element, Color color)
{
foreach (IShape shape in element.Shapes())
{
shape.Color = color;
}
}
/// <summary>
/// This example deals only with a subset of the standard stereotypes.
/// </summary>
private Color? ColorForStereotype(string name)
{
switch (name)
{
case "focus": return Color.AliceBlue;
case "auxiliary": return Color.Bisque;
case "specification": return Color.OliveDrab;
case "realization": return Color.LightSeaGreen;
case "implementationClass": return Color.PaleGoldenrod;
}
return null;
}
}}
規則の定義
規則を定義して、VMSDK ストア内の変更を反映させることができます。 トリガーする変更と規則はどちらも同じトランザクション内で実行されます。 ユーザーが [元に戻す] コマンドを呼び出した場合は、両方の変更が一緒に元に戻されます。
前の例の欠点は、イベント ハンドラーを使用して形状の色を変更することです。 色は VMSDK ストアのフィールドにもアタッチされているので、トランザクション内で実行する必要があります。 その結果、ステレオタイプの適用後にユーザーが [元に戻す] コマンドを呼び出すと、色の変更は元に戻されますが、ステレオタイプは適用されたまま残ります。 ステレオタイプの適用を解除するには、[元に戻す] コマンドを再実行する必要があります。 場合によってはこれで目的が達成されますが、達成されない場合は規則を定義することで、1 つのトランザクション内ですべての変更を反映させることができます。
規則はストアの外部の変更を反映させる場合には不便です。ユーザーが [元に戻す] または [やり直し] コマンドを実行するときには規則は呼び出されないためです。
規則は規則マネージャーを使用して登録するクラスです。 通常、VMSDK コードを作成するときは、属性をクラスにアタッチし、拡張コードの読み込み時に読み取られるリストにクラスを含めることで、規則を登録します。 ただし、UML の実装は既にコンパイルされているので、規則を規則マネージャーに動的に追加する必要があります。 例に示すコードは現在の実装規則管理に大きく依存していますが、この実装規則管理は将来のリリースで変更される可能性があります。
規則を追加するには、実装クラスの名前を把握しておく必要があります。 これらは将来のリリースで変更される可能性があります。 できる限り、IClass、IProfile などの UML API の種類に要素をキャストしてください。
ここに示す例では、UML モデル内のオブジェクトの追加と削除を処理する規則を示しています。 オブジェクトのプロパティの変更に応答する規則を作成することもできます。 詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
例: 規則を使用した、ステレオタイプによるクラスの色分け
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Drawing;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Validation;
using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.Uml.UseCases;
using Microsoft.VisualStudio.Uml.ModelStore; // in private assembly. Used for Get|IsElementDefinition()
namespace UmlRules
{
class ColorByStereotype
{
/// <summary>
/// Singleton wrappers: one per model.
/// </summary>
private static Dictionary<IPackage, ColorByStereotype > modelAdapters =
new Dictionary<IPackage, ColorByStereotype >();
private class Wrapper
{
/// <summary>
/// This isn't actually validation.
/// It sets up some store rules.
/// The validation package creates an instance of this class and then calls this method.
/// See "Validation": https://msdn.microsoft.com/library/bb126413.aspx
/// </summary>
/// <param name="vcontext"></param>
/// <param name="model"></param>
[Export(typeof(System.Action<ValidationContext, object>))]
[ValidationMethod(ValidationCategories.Open)]
private void ConnectAdapterToModel(ValidationContext vcontext, IModel model)
{
modelAdapters.Add(model, new ColorByStereotype (model));
}
}
private IModel model;
private Store store;
private ColorByStereotype (IModel model)
{
this.model = model;
// This is the underlying DSL store, not the wrapping UML ModelStore:
store = (model as ModelElement).Store;
SetRule<StereotypeInstanceAddedRule>(
store.DomainDataDirectory.FindDomainClass(
"Microsoft.VisualStudio.Uml.Classes.StereotypeInstance"));
// For the deletion, we need to trigger from the deleted link
// between the stereotype instance and the model element -
// because after deletion we can't find the element from the stereotype instance.
SetRule<StereotypeInstanceDeletedRule>(
store.DomainDataDirectory.FindDomainRelationship(
"Microsoft.VisualStudio.Uml.Classes.ElementHasAppliedStereotypeInstances"));
}
/// <summary>
/// Register a rule.
/// Normally, you set a rule by prefixing the rule class with
/// [RuleOn(typeof(TargetClass))]
/// but we are setting up the rule at runtime, so must add
/// the rules to the relevant dictionaries.
/// </summary>
/// <typeparam name="T">Rule class</typeparam>
/// <param name="classInfo">Class or relationship to which to attach the rule.</param>
private void SetRule<T>(DomainClassInfo classInfo) where T : Rule, new()
{
T rule = new T();
rule.FireTime = TimeToFire.TopLevelCommit;
System.Type tt = typeof(T);
string ruleSet = (typeof(AddRule).IsAssignableFrom(tt)) ? "AddRules" :
(typeof(ChangeRule).IsAssignableFrom(tt)) ? "ChangeRules" :
(typeof(DeleteRule).IsAssignableFrom(tt)) ? "DeleteRules" :
(typeof(DeletingRule).IsAssignableFrom(tt)) ? "DeletingRules" : "";
// The rest of this method uses reflection to achieve the following:
// store.RuleManager.RegisterRule(rule);
// classInfo.AddRules.Add(rule);
System.Reflection.BindingFlags privateBinding =
System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.NonPublic;
System.Reflection.MethodInfo mi =
typeof(RuleManager).GetMethod("RegisterRule", privateBinding);
mi.Invoke(store.RuleManager, new object[] { rule });
store.RuleManager.EnableRule(typeof(T));
System.Reflection.PropertyInfo pi =
typeof(DomainClassInfo).GetProperty(ruleSet, privateBinding);
dynamic rules = pi.GetValue(classInfo, null);
System.Type ruleListType = rules.GetType();
System.Reflection.FieldInfo listpi =
ruleListType.GetField("list", privateBinding);
dynamic list = listpi.GetValue(rules);
System.Type listType = list.GetType();
System.Reflection.MethodInfo addmi = listType.GetMethod("Add");
addmi.Invoke(list, new object[] { rule });
System.Reflection.MethodInfo resetRulesCache =
typeof(DomainClassInfo).GetMethod("ResetRulesCache", privateBinding);
resetRulesCache.Invoke(classInfo, null);
}
#region Rules.
private class StereotypeInstanceAddedRule : AddRule
{
public override void ElementAdded(ElementAddedEventArgs e)
{
base.ElementAdded(e);
Store store = e.ModelElement.Store;
// Don't handle load from file:
if (store.InSerializationTransaction)
return;
IStereotypeInstance si = e.ModelElement as IStereotypeInstance;
IElement umlElement = si.Element;
// Work only with the core model, not the views:
if (!umlElement.IsElementDefinition()) return;
// I'm only interested in coloring classes and interfaces:
if (!(umlElement is IType)) return;
Color? color = ColorForStereotype(si.Name);
if (color.HasValue)
{
SetColorOfShapes(si.Element, color.Value);
}
}
}
private class StereotypeInstanceDeletedRule : DeleteRule
{
public override void ElementDeleted(ElementDeletedEventArgs e)
{
base.ElementDeleted(e);
Store store = e.ModelElement.Store;
// Use the generic link type to avoid using the UML implementation DLL:
ElementLink elementToStereotypeLink = e.ModelElement as ElementLink;
IElement umlElement = elementToStereotypeLink.LinkedElements[0] as IElement;
// Work only with the core model, not the views:
if (!umlElement.IsElementDefinition()) return;
// We're here either because a stereotype is being un-applied,
// or because the uml element is being deleted.
// Don't bother if the element is being deleted:
if ((umlElement as ModelElement).IsDeleting) return;
// We're only interested in classes and interfaces:
if (!(umlElement is IType)) return;
// Because more than one stereotype can be applied to an element,
// we should check to see if there are any remaining:
Color newColor = Color.WhiteSmoke; // Default if there aren't.
foreach (IStereotypeInstance remainingSi in umlElement.AppliedStereotypes)
{
Color? color = ColorForStereotype(remainingSi.Name);
if (color.HasValue)
{
newColor = color.Value;
break;
}
}
SetColorOfShapes(umlElement, newColor);
}
}
/// <summary>
/// Set the color of the shapes that display an element.
/// </summary>
/// <param name="element"></param>
/// <param name="color"></param>
private static void SetColorOfShapes(IElement element, Color color)
{
foreach (IShape shape in element.Shapes())
{
shape.Color = color;
}
}
/// <summary>
/// For this sample, we just deal with some of the standard stereotypes.
/// </summary>
/// <param name="name">Stereotype name</param>
/// <returns></returns>
private static Color? ColorForStereotype(string name)
{
switch (name)
{
case "focus": return Color.AliceBlue;
case "auxiliary": return Color.Bisque;
case "specification": return Color.OliveDrab;
case "realization": return Color.LightSeaGreen;
case "implementationClass": return Color.PaleGoldenrod;
}
return null;
}
#endregion
}
}
例: 既定では双方向の関連
既定では、クラス図に関連を描画した場合、新しい関連は 1 つの方向のみに移動できます。 関連には片方の末尾に矢印が付いています。 目的によっては、矢印のない、双方向の関連を描画した方が便利なことがあります。 以下の規則を追加すると、双方向の関連を既定にすることができます。
/// <summary>
/// Rule invoked when an Association is created.
/// This rule sets both ends navigable, which is convenient for representing requirements.
/// </summary>
private class AssociationAddRule : AddRule
{
public override void ElementAdded(ElementAddedEventArgs e)
{
Store store = e.ModelElement.Store;
IAssociation association = e.ModelElement as IAssociation;
// Do not apply the rule if we are reading from file or undoing a deletion:
if (association.MemberEnds.Count() == 0
|| store.InSerializationTransaction || store.InUndoRedoOrRollback) return;
// Do not apply the rule unless a containing package or model has imported
// a profile that defines the stereotype "Default Binary Associations" for associations:
// if (!association.ApplicableStereotypes.Any
// (s => s.DisplayName == "Default Binary Associations")) return;
// Don’t apply the rule to use cases:
if (!(association.SourceElement is IUseCase && association.TargetElement is IUseCase))
{
association.OwnedEnds.First().SetNavigable(true);
association.OwnedEnds.Last().SetNavigable(true);
}
}
}
規則を登録するには、「規則の定義」で説明されている SetRule メソッドを使用する必要があります。
SetRule<AssociationAddRule>(store.DomainDataDirectory.
FindDomainRelationship("Microsoft.VisualStudio.Uml.Classes.Association"));
この規則を有効または無効にできるようにする 1 つの方法は、特定のステレオタイプが定義されるプロファイルを定義することです。 規則には、プロファイルが格納元のパッケージまたはモデルで有効になっていることを検証するためのコードを追加できます。 詳細については、「方法: プロファイルを定義して UML を拡張する」を参照してください。
コア モデルとビュー モデル
UML モデルは複数の VMSDK (DSL) モデルで構成されています。
コア モデルには、UML モデル内の要素すべての表現が含まれています。 ユーザーは [UML モデル エクスプローラー] ウィンドウでこれらの要素を表示できます。これらの要素には UML ModelStore API を経由してアクセスできます。 コア モデルは 1 つの VMSDK ストア パーティションに格納されます。
UML プロジェクト内の UML 図ごとに、1 つのビュー モデルが存在します。 各ビュー モデル内のオブジェクトは、コア モデル内のオブジェクトのプロキシです。 UML 図に表示される要素ごとにビュー モデル オブジェクトが存在します。 各ビュー モデルは 1 つの VMSDK ストア パーティションに格納されます。
図に表示される要素ごとに、1 つの VMSDK 形状オブジェクトが存在します。 ビュー モデルの要素と形状には 1 対 1 の関係が存在します。
規則またはイベント ハンドラーを定義すると、これらはどちらもコア オブジェクトまたはビュー オブジェクトが変更されたときに呼び出されます。 コア オブジェクトへの変更のみを処理するようにしてください。 この例のハンドラーでは element.IsElementDefinition() を使用して、コア オブジェクトを処理しているかどうかを判断します。
このメソッドを使用するには、次のファイルへのプロジェクト参照を追加する必要があります。
%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.Uml.dll
ヒント
プライベート アセンブリで定義された IsElementDefinition および他のメソッドは、将来のリリースで変更される可能性があります。
using Microsoft.VisualStudio.Uml.ModelStore;
// in private assembly. Used for GetElementDefinition()
...
// Determine whether an element is view or core:
if (anElement.IsElementDefinition())
{ /* core */ }
else
{ /* view */ }
...
// If shapeElement is a shape on a diagram -
// The VMSDK element connected to the shape is in the view:
IElement viewModelElement = shapeElement.ModelElement as IElement;
// Get the core element for which the view is a proxy:
IElement coreModelElement = viewModelElement.GetElementDefinition();
...
参照
処理手順
その他の技術情報
Sample: Color by Stereotype (サンプル: ステレオタイプにより色分けする)
履歴の変更
日付 |
履歴 |
理由 |
---|---|---|
2011 年 3 月 |
トピックを作成。 |
カスタマー フィードバック |