作成しモデル要素を削除しプロパティを設定して要素間のリンクを作成および削除するためのコードを記述できます。 すべての変更はトランザクション内で行う必要があります。 要素が図に表示される場合この図はトランザクションの終了時に自動的に 「です。
このトピックの内容
DSL の定義例
モデルの移動
クラス情報へのアクセス
トランザクション内の変更を実行します。
モデル要素の生成
リンクの関係の作成
要素の削除
関係のリンクの削除
リンクの関係の順序の変更
ロック
コピーして貼り付けます。
図を表示および更新する
図形要素と要素の間の移動
シェイプとコネクタのプロパティ
DocView と DocData
モデル要素へコネクタの図形と図およびリレーションシップが別のトピックで説明します。 詳細については、「[リダイレクト] 方法: 図内を移動し、また、図を更新する」を参照してください。
DSL の定義例
このトピックの例の DslDefinition.dsl の本体部分です :
このモデルはDSL のインスタンスです :
参照と名前空間
このトピックのコードを実行するには参照する必要があります :
Microsoft.VisualStudio.Modeling.Sdk.11.0.dll
このコードは名前空間を使用する :
using Microsoft.VisualStudio.Modeling;
またDSL を定義する別のプロジェクトのコードを記述する場合はDsl プロジェクトによってビルドされたアセンブリをインポートする必要があります。
モデルの移動
プロパティ
DSL定義で定義するドメインのプロパティはプログラム コードでアクセスできるプロパティです :
Person henry = ...;
if (henry.BirthDate < 1500) ...
if (henry.Name.EndsWith("VIII")) ...
プロパティを設定する場合は トランザクション 内で実行する必要があります :
henry.Name = "Henry VIII";
DSL を定義してプロパティの 種類 は *** Calculated *** で設定できません。 詳細については、「計算プロパティおよびカスタム格納プロパティ」を参照してください。
関係
DSL定義で定義するドメイン関係プロパティは関係の両端のクラスの 1 のペアになります。 プロパティの名前はリレーションシップの両側にロールのラベルとして DslDefinition の図に表示されます。 ロールの多重度によってプロパティの型はリレーションシップの反対側にクラスまたはそのクラスのコレクションです。
foreach (Person child in henry.Children) { ... }
FamilyTreeModel ftree = henry.FamilyTreeModel;
リレーションシップの反対側のプロパティは常にです。 リンクを作成または削除されると両方の要素のプロパティにが更新されます。 (System.Linq の拡張子を使用) 次の例の式 ParentsHaveChildren の関係についても同様です : 必ず
(Person p) => p.Children.All(child => child.Parents.Contains(p))
&& p.Parents.All(parent => parent.Children.Contains(p));
ElementLinks。 リレーションシップはドメイン リレーションシップの型のインスタンスである と いう リンク されたモデル要素によって表されます。 リンクの上に 1 本のソース要素と 1 のターゲット要素が必要です。 ソース要素とターゲット要素には同じになります。
リンクやプロパティにアクセスできます :
ParentsHaveChildren link = ParentsHaveChildren.GetLink(henry, edward);
// This is now true:
link == null || link.Parent == henry && link.Child == edward
既定ではリレーションシップの複数のインスタンスがモデル要素のペアをリンクできません。 ただしDSL 定義でAllow Duplicates フラグの関係についても同様複数のリンクがあると GetLinks を使用する必要があります :
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinks(henry, edward)) { ... }
またリンクにアクセスするための他の方法があります。 次に例を示します。
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinksToChildren(henry)) { ... }
非表示のロール。DSL 定義で*** Is Property Generated *** に特定のロールの *** false *** でそのロールに対応するプロパティは生成されません。 ただしリンクへのアクセスリレーションシップのメソッドを使用してリンクをスキャンできます :
foreach (Person p in ParentsHaveChildren.GetChildren(henry)) { ... }
最もよく使用される表示する図の例では図形モデル要素リンクを PresentationViewsSubject のリレーションシップです :
PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape
要素のディレクトリ
要素のディレクトリを使用してストアのすべての要素にアクセスできます :
store.ElementDirectory.AllElements
は次のような要素を検索するためのメソッドがあります :
store.ElementDirectory.FindElements(Person.DomainClassId);
store.ElementDirectory.GetElement(elementId);
クラス情報へのアクセス
DSL を定義するクラスリレーションシップおよびそのほかの側面に関する情報を取得できます。 次に例を示します。
DomainClassInfo personClass = henry.GetDomainClass();
DomainPropertyInfo birthProperty =
personClass.FindDomainProperty("BirthDate")
DomainRelationshipInfo relationship =
link.GetDomainRelationship();
DomainRoleInfo sourceRole = relationship.DomainRole[0];
モデル要素の先祖のクラスは次のとおりです。:
ModelElement - すべての要素と関係は ModelElements。
ElementLink - すべての関係は ElementLinks。
トランザクション内の変更を実行します。
プログラム コードがストアのコードを変更するたびにトランザクション内で実行する必要があります。 これはすべてのモデル要素関係図形ダイアグラムおよびプロパティに適用されます。 詳細については、「Transaction」を参照してください。
トランザクションを管理する最も簡単な方法は try...catch のステートメントで囲まれた using のステートメントです :
Store store; ...
try
{
using (Transaction transaction =
store.TransactionManager.BeginTransaction("update model"))
// Outermost transaction must always have a name.
{
// Make several changes in Store:
Person p = new Person(store);
p.FamilyTreeModel = familyTree;
p.Name = "Edward VI";
// end of changes to Store
transaction.Commit(); // Don't forget this!
} // transaction disposed here
}
catch (Exception ex)
{
// If an exception occurs, the Store will be
// rolled back to its previous state.
}
1 回のトランザクション内の変更の数を設定できます。 アクティブなトランザクション内で新しいトランザクションを開くことができます。
破棄される前にすべての変更を永続化するにはCommit トランザクション必要があります。 トランザクション内でキャッチされない例外が発生した場合ストアは変更前の状態にリセットされます。
モデル要素の生成
この例は既存のモデルに要素を追加します :
FamilyTreeModel familyTree = ...; // The root of the model.
using (Transaction t =
familyTree.Store.TransactionManager
.BeginTransaction("update model"))
{
// Create a new model element
// in the same partition as the model root:
Person edward = new Person(familyTree.Partition);
// Set its embedding relationship:
edward.FamilyTreeModel = familyTree;
// same as: familyTree.People.Add(edward);
// Set its properties:
edward.Name = "Edward VII";
t.Commit(); // Don't forget this!
}
この例では要素の作成に関する次のようなポイントを示します :
ストアの特定のパーティションに新しい要素を生成します。 モデル要素および関係が図形これに対して既定のパーティションは通常です。
埋め込みリレーションシップにはターゲットを実行します。 この例の DslDefinition では各メンバーはリレーションシップを FamilyTreeHasPeople 埋め込みのターゲットである必要があります。 これを実現するためにPerson オブジェクトのプロパティ FamilyTreeModel のロールを設定することができます。または FamilyTreeModel のオブジェクトのプロパティのユーザーのロールにユーザーを追加します。
特にプロパティが IsName DslDefinition に当てはまる新しい要素のプロパティを設定します。 このフラグは所有者内で要素を識別するために使用するプロパティを示します。 この場合名前のプロパティにフラグがあります。
この DSL の DSL 定義はストアに読み込まれている必要があります。 メニュー コマンドなどの拡張機能を作成する場合通常は既に同じです。 またストアに明示的にモデルを読み込むことができます。また読み込みに ModelBus を使用します。 詳細については、「方法: プログラム コード内のファイルからモデルを開く」を参照してください。
要素をこのように作成する場合シェイプは自動的に (DSL) の場合図が作成されます。 これは既定の図形色およびそのほかの機能と自動的に割り当てられた位置に表示されます。 関連の図形が表示される場所と制御するには 要素および図形の作成 を参照してください。
リンクの関係の作成
DSL の定義例で定義される 2 種類の関係にあります。 各リレーションシップは関係の両端のクラスの プロパティのロール 定義します。
リレーションシップのインスタンスを作成する方法の 3 つがあります。 これらの 3 個の各メソッドは同じ効果があります :
ロール プレーヤーのソースのプロパティを設定します。 次に例を示します。
familyTree.People.Add(edward);
edward.Parents.Add(henry);
対象のロール プレーヤーのプロパティを設定します。 次に例を示します。
edward.familyTreeModel = familyTree;
このロールの多重度が 1..1 なのでその値を割り当てます。
henry.Children.Add(edward);
このロールの多重度が 0..* といるためコレクションに追加します。
リレーションシップのインスタンスを明示的に作成します。 次に例を示します。
FamilyTreeHasPeople edwardLink = new FamilyTreeHasPeople(familyTreeModel, edward);
ParentsHaveChildren edwardHenryLink = new ParentsHaveChildren(henry, edward);
最後のメソッドはリレーションシップのプロパティ自体にする場合に便利です。
要素をこのように作成するとダイアグラムのコネクタが自動的に作成されますが既定の図形色およびそのほかの機能があります。 関連するコネクタの作成方法を制御するには 要素および図形の作成 を参照してください。
要素の削除
Delete() を呼び出して要素を削除します :
henry.Delete();
この操作も削除されます :
要素間の関係にリンクします。 たとえばedward.Parents はhenry は含まれません。
PropagatesDelete フラグが true になる要素のロール。 たとえば要素を表示している図形は削除されます。
既定では埋め込みリレーションシップにターゲットのロールでPropagatesDelete があります。 henry を削除する familyTree を削除しませんがfamilyTree.Delete() はすべての Persons を削除します。 詳細については、「削除動作のカスタマイズ」を参照してください。
既定ではは PropagatesDelete 参照リレーションシップの役割についても変換。
オブジェクトを削除すると特定の伝達を省略して削除規則が発生する可能性があります。 これは別の 1 要素に置換する場合に便利です。 削除に反映されないように一つ以上のロールの GUID を指定します。 GUID はリレーションシップ クラスから派生する場合 :
henry.Delete(ParentsHaveChildren.SourceDomainRoleId);
(この例は PropagatesDelete が ParentsHaveChildren の関係のロールの false であるため効果はありません)。
場合によっては削除は要素または伝達によって削除される要素のロックの手順ではできません。 要素を削除できるかどうかを確認するにはelement.CanDelete() を使用できます。
関係のリンクの削除
ロールのプロパティから要素を削除してリレーションシップのリンクを削除できます :
henry.Children.Remove(edward); // or:
edward.Parents.Remove(henry); // or:
またリンクを明示的に削除できます :
edwardHenryLink.Delete();
この 3 種類のメソッドはすべて同じ効果があります。 これらの 1 のみ使用する必要があります。
ロールで 0..1 または 1..1 多重度がある場合はnullまたは別の値に設定できます :
edward.FamilyTreeModel = null; または //:
edward.FamilyTreeModel = anotherFamilyTree;
リンクの関係の順序の変更
特定のモデル要素で指定されているまたはを対象とする特定の関係のリンクに特定のシーケンスがあります。 これらは追加された順序で表示されます。 たとえばこのステートメントは同じ順序で子を常にあります :
foreach (Person child in henry.Children) ...
リンクの順序を変更できます :
ParentsHaveChildren link = GetLink(henry,edward);
ParentsHaveChildren nextLink = GetLink(henry, elizabeth);
DomainRoleInfo role =
link.GetDomainRelationship().DomainRoles[0];
link.MoveBefore(role, nextLink);
ロック
変更はロックについて場合があります。 ロックは個々の要素パーティションストアで設定できます。 これらのレベルのいずれかがようにするの変更を防止する場合ロックを試みると例外がスローされることがあります。 () でのロックが Immutability で定義されている拡張メソッドである element.GetLocks を使用して設定するかどうかを確認できます。
詳細については、「ロック ポリシーの定義と読み取り専用セグメントの作成」を参照してください。
コピーして貼り付けます。
IDataObject に要素または要素グループをコピーする場合 :
Person person = personShape.ModelElement as Person;
Person adopter = adopterShape.ModelElement as Person;
IDataObject data = new DataObject();
personShape.Diagram.ElementOperations
.Copy(data, person.Children.ToList<ModelElement>());
要素はシリアル化された要素のグループとして格納されます。
モデルに IDataObject の要素をマージするには :
using (Transaction t = targetDiagram.Store.
TransactionManager.BeginTransaction("paste"))
{
adopterShape.Diagram.ElementOperations.Merge(adopter, data);
}
Merge () は PresentationElement または ModelElement を使用できます。 これに PresentationElement を設定すると3 番目のパラメーターとしてコピー先のダイアグラムの場所を指定できます。
図を表示および更新する
DSL では個人または曲のような概念を表すドメイン モデル要素を表すシェイプの要素と図に表示されることがあります。 ドメイン モデルの要素は概念の重要なプロパティとリレーションシップを保存します。 図形の要素を図でオブジェクトのビューのサイズ位置および色およびコンポーネント部分のレイアウト保存します。
プレゼンテーションの要素
DSL 定義では指定した各要素には以下の標準クラスの 1 つがから派生したクラスを作成します。
要素の型 |
[基本クラス] |
---|---|
ドメイン クラス |
|
ドメイン リレーションシップ |
|
Shape |
|
コネクタ |
|
Diagram |
図の要素はモデル要素を表します。 通常は (ただし常にNodeShape ドメインにクラスのインスタンスをBinaryLinkShape はドメイン リレーションシップのインスタンスを表します。 PresentationViewsSubject の関係を表すモデル要素にノードまたはリンクの図形をリンクします。
すべてのノードまたはリンクの図形は 1 種類の図に属しています。 バイナリ リンクの図形は 2 ノードの図形を接続します。
図形は 2 セットの機能の形状を持つことができます。 NestedChildShapes の図形は親の境界ボックスに制限されます。 RelativeChildShapes の一覧の図形は親 (たとえばラベルまたはポートの範囲外で外部で部分的に指定できます。 図に RelativeChildShapes と Parent はありません。
図形要素と要素の間の移動
ドメイン モデル要素と図形要素は PresentationViewsSubject のリレーションシップに関連付けられます。
// using Microsoft.VisualStudio.Modeling;
// using Microsoft.VisualStudio.Modeling.Diagrams;
// using System.Linq;
Person henry = ...;
PersonShape henryShape =
PresentationViewsSubject.GetPresentation(henry)
.FirstOrDefault() as PersonShape;
同じ関係が図の形式との関係をリンク :
Descendants link = Descendants.GetLink(henry, edward);
DescendantConnector dc =
PresentationViewsSubject.GetPresentation(link)
.FirstOrDefault() as DescendantConnector;
// dc.FromShape == henryShape && dc.ToShape == edwardShape
この関係は図にモデルのルートをリンク :
FamilyTreeDiagram diagram =
PresentationViewsSubject.GetPresentation(familyTree)
.FirstOrDefault() as FamilyTreeDiagram;
モデル要素を図形によって表される取得するには使用 :
henryShape.ModelElement as Person
diagram.ModelElement as FamilyTreeModel
図の間の移動
一般に図のシェイプとコネクタの間で移動するには勧められません。 図で実行する必要がある場合にのみシェイプとコネクタの間で移動するモデルの関係を移動することをお勧めします。 これらのメソッドは各端のシェイプとコネクタをリンク :
personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes
connector.FromShape, connector.ToShape
多くの複合図形はありません ; これらは子の親シェイプと一つ以上のレイヤーで構成されます。 別のシェイプに関連して配置される図形は 子 であると呼ばれます。 親シェイプが移動すると子に移動します。
相対子は 親シェイプの境界ボックスの外に表示できます。 入れ子になった 子は親の境界内でのみ表示されます。
ダイアグラムの図形の設定を取得するには使用 :
Diagram.NestedChildShapes
シェイプとコネクタの先祖のクラスは次のとおりです :
-- ShapeElement
----- NodeShape
------- Diagram
------- YourShape
----- LinkShape
------- BinaryLinkShape
--------- YourConnector
シェイプとコネクタのプロパティ
ほとんどの場合図形に明示的な変更を加える必要はありません。 モデル要素を変更する場合は「規則を更新するシェイプとコネクタを修正。 詳細については、「変更内容への対応および変更内容の反映」を参照してください。
ただし図形について明示変更を加えるとモデル要素とは無関係のプロパティに便利です。 たとえば次のプロパティを変更できます :
Size - 図形の高さと幅が決まります。
-Location 親シェイプまたは図に関連する場所
-StyleSet ペンとブラシの設定はシェイプまたはコネクタを描画するために使用する
- 図形を非表示にします Hide
Show - 図形を Hide() の後に表示されるようにします。
要素および図形の作成
要素を作成しリレーションシップを埋め込みのツリーにリンクすると図形に自動的に作成され関連付けられます。 これはトランザクションの最後に実行する 「フィックスアップ」によってされます。 ただし図形は自動的に割り当てられる位置に表示され図形に色およびそのほかの機能に既定値が設定されます。 図形の作成方法を制御するにはマージの関数を使用します。 最初にElementGroup に追加する要素を追加しダイアグラムにマージします。
このメソッドでは、次の処理が実行されます。
要素名としてプロパティを割り当てる名前を設定します。
DSL定義で指定した要素のマージのディレクティブを確認します。
この例ではマウスの位置でユーザーだけがダブル クリックすると図形を作成します。 このサンプルの DSL の定義ではExampleShape の FillColor のプロパティが公開されています。
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
partial class MyDiagram
{
public override void OnDoubleClick(DiagramPointEventArgs e)
{
base.OnDoubleClick(e);
using (Transaction t = this.Store.TransactionManager
.BeginTransaction("double click"))
{
ExampleElement element = new ExampleElement(this.Store);
ElementGroup group = new ElementGroup(element);
{ // To use a shape of a default size and color, omit this block.
ExampleShape shape = new ExampleShape(this.Partition);
shape.ModelElement = element;
shape.AbsoluteBounds = new RectangleD(0, 0, 1.5, 1.0);
shape.FillColor = System.Drawing.Color.Azure;
group.Add(shape);
}
this.ElementOperations.MergeElementGroupPrototype(
this,
group.CreatePrototype(),
PointD.ToPointF(e.MousePosition));
t.Commit();
}
}
}
いくつかの図形を提供しAbsoluteBounds を使用して相対位置を設定します。
このメソッドを使用してコネクタの色やそのほかの公開するプロパティを設定できます。
トランザクションを使用します。
図形と図はコネクタ ModelElement のサブタイプでストアに置かれます。 したがってトランザクション内でのみに変更を加える必要があります。 詳細については、「方法: トランザクションを使用してモデルを更新する」を参照してください。
ドキュメントとドキュメント データの表示
パーティションを保存します。
モデルを読み込むときに含まれる図は同時に読み込まれます。 通常モデルは Store.DefaultPartition に読み込まれダイアグラムの内容が別のパーティションに読み込まれます。 通常各パーティションの内容が読み込まれ別のファイルに格納されます。
参照
関連項目
概念
Visual Studio Modelbus によるモデルの統合