要素作成処理および要素移動処理のカスタマイズ
要素をツールボックスからまたは貼り付け移動操作の一つにドラッグを許可できます。 指定したリレーションシップを使ってターゲットの要素にリンク移動した要素を持つことができます。
要素のマージのディレクティブは (EMD)1 種類のモデル要素を別のモデル要素に マージ したときの動作を指定します。 これは次の場合に発生します :
ユーザーが図または図形にツールボックスからドラッグします。
ユーザーはエクスプローラーまたは図形のコンパートメントで追加のメニューを使用して要素を作成します。
ユーザーが 1 スイムレーン間で項目を移動します。
ユーザーが要素を貼り付けます。
プログラム コードは要素のマージのディレクティブを呼び出します。
作成処理がコピー操作とは異なるように見えることがありますが同じです。 要素が追加されるとたとえばツールボックスからそのプロトタイプは複製されます。 プロトタイプはモデル内の他の部分からコピーした要素と同様モデルにマージされます。
EMD の責任はオブジェクトまたはオブジェクトのグループをモデルの特定の位置にマージするかを決定します。 特にモデルにマージされたグループをリンクするにはリレーションシップのインスタンスを作成するかを決定します。 また設定のプロパティにこれをカスタマイズして追加的なオブジェクトを作成できます。
要素のマージのディレクティブのロール
EMD は埋め込む関係を定義すると自動的に生成されます。 ユーザーが親に新しい子のインスタンスを追加するとこの既定 EMD はリレーションシップのインスタンスを作成します。 既定値 EMDs を変更できます。たとえばカスタム コードを追加してこれらの。
ユーザーがドラッグするかまたはマージされ受け取る側のクラスのさまざまな組み合わせを貼り付けるに DSL 定義の独自の EMDs を追加できます。
要素のマージのディレクティブの定義
ドメイン クラスドメイン リレーションシップコネクタ図形と図に要素のマージにディレクティブを追加できます。 受信するドメイン クラスで DSL のエクスプローラーで追加するかまたは検索できます。 受信するクラスは新規またはコピーがマージされている要素がモデルに存在する要素のドメイン クラスです。
*** Indexing Class *** は受け取る側のクラスのメンバーにマージできる要素のドメイン クラスです。 インデックスのクラスのサブクラスのインスタンスはこの EMD によって *** Applies to subclasses *** を false に設定するマージされます。
2 種類のマージのディレクティブが含まれます :
マージ プロセスの ディレクティブは新しい要素をツリーにリンクさせる関係を指定します。
[マージの ディレクティブは別の受信する要素 (通常は親に新しい要素をリダイレクトします。
マージのディレクティブにカスタム コードを追加できます :
独自のコードを要素のインデックスの特定のインスタンスがターゲット要素にマージするかどうかを判断するために追加するに *** Uses custom accept *** を設定します。 ユーザーがツールボックスからドラッグすると「無効な」ポインターはコードをマージを拒否すると表示されます。
たとえば受け取る側の要素が特定の状態にある場合にのみマージにすることができます。
追加するに *** Uses custom merge *** をマージが発生したときにモデルに対する変更を定義するために使用する独自のコードを設定します。
たとえばモデルで新しい場所からデータを使用してマージされた要素のプロパティを設定できます。
注意
マージ カスタム コードを記述する場合はこの EMD を使用してマージにのみ影響します。他の EMDs である場合オブジェクトの型をマージするまたは EMD を使用せずにこれらのオブジェクトを作成するそのほかのカスタム コードがある場合はカスタム マージ コードによる影響を受けません。
新しい要素または新しいリレーションシップをカスタム コードによって常に処理されるようにするには埋め込みリレーションシップの AddRule および要素のドメイン クラス DeleteRule を定義することを検討してください。詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
例 : カスタム コードのない EMD の定義
次の例ではユーザーが既存の図形にツールボックスからドラッグして要素およびコネクタを同時に作成することもできます。 この例ではDSL 定義に EMD を追加します。 この変更の前にユーザーが図に既存の図形にツールをドラッグできます。
ユーザーは他の要素に要素を貼り付けることができます。
ユーザーが要素およびコネクタを同時に作成するには
*** Minimal Language *** のソリューション テンプレートを使用して新しい DSL を作成します。
この DSL を実行すると図形間のシェイプとコネクタを作成することができます。 既存の図形にツールボックスから *** ExampleElement *** の新しい図形をドラッグすることはできません。
ユーザーを ExampleElement の図形に要素をマージすることを許可するには ExampleElement のドメイン クラスの新しい EMD の作成 :
*** DSL Explorer *** ではENT6ENT を配置する。 ExampleElement を右クリックしを ENT0ENT [] をクリックします。
新しい EMD の詳細を表示できるように ENT1ENT [出力] ウィンドウが開いていることを確認します。 (メニューでの操作 : 表示 その他のウィンドウ *** DSL Details ***)。
要素のクラスが ExampleElement のオブジェクトにマージできます。または定義するに DSL の詳細] ウィンドウの *** Indexing class *** を設定します。
この例ではユーザーが既存の要素に新しい要素をドラッグできるように[ExampleElements。
インデックスのクラスが DSL のエクスプローラー EMD の名前になっていることに注意してください。
*** Process merge by creating links *** の下に2 回のパスを追加します :
1 回のパスは親に新しいモデル要素にリンクします。 ユーザーが入力する必要があるパス式はモデルに埋め込む関係での先頭にある既存の要素を移動します。 最後に新しい要素が割り当てられた新しいリンクのロールを指定します。 パスは次のとおりです。:
ExampleModelHasElements.ExampleModel/!ExampleModel/.Elements
他のパスは既存の要素に新しい要素をリンクします。 パス式は新しい要素に割り当てられたロールと参照の関係を指定します。 このパスは次のとおりです。:
ExampleElementReferencesTargets.Sources
各パスを作成するためにパスのナビゲーション ツールを使用して :
*** Process merge by creating links at paths *** でENT4ENT [] をクリックします。
リスト項目の右側にあるドロップダウン矢印をクリックします。 ツリー ビューが表示されます。
指定するパスを形成するツリー ノードを展開します。
DSL をテストする :
ソリューションを再度ビルドして実行するにはF5 キーを押します。
ビルドし直すと生成されたコードはテキスト テンプレートから新しいユース定義に準拠するように更新されるため通常は時間がかかります。
Visual Studio の実験用インスタンスが開始されるとDSL モデル ファイルを開きます。 使用例に要素を作成します。
既存の図形に ENT0ENT [入力] ツールをドラッグします。
新しい図形が表示されコネクタで既存の図形にリンクします。
既存の図形をコピーします。 別のシェイプを選択し貼り付けます。
最初の図形のコピーが作成されます。 新しい名前でありコネクタに 2 番目の図形にリンクします。
この手順では次の点に注意してください :
要素のマージのディレクティブを作成して要素のクラスが他の受け取ることができるできます。 EMD は受け取る側のドメイン クラスで作成され承認済みドメインのクラスは ENT1ENT [入力] フィールドで指定されます。
パスの定義に使用されるリンク既存のモデルに新しい要素を接続するかを指定できます。
指定したリンクは1 種類の埋め込みリレーションシップを含める必要があります。
EMD はツールボックスから作成および貼り付け操作の両方に影響します。
新しい要素を作成するカスタム コードを記述する場合はElementOperations.Merge のメソッドを使用して明示的に EMD を呼び出すことができます。 このエラーは他の処理と同様モデルに新しい要素をリンクすることになります。 詳細については、「コピー動作のカスタマイズ」を参照してください。
例 : 使用 EMD にカスタム コードを追加できます。
EMD にカスタム コードを追加することによりより複雑なマージ動作を定義できます。 この例ではユーザーが図に要素の数より多くを追加することはできません。 この例では埋め込みリレーションシップに含まれる既定 EMD を変更します。
カスタム コードをユーザーが使用できるように制限するに追加するには
*** Minimal Language *** のソリューション テンプレートを使用してDSL を作成します。 DSL 定義図を開きます。
DSL のエクスプローラーでExampleModel***** Element Merge Directives *****ENT2ENT を配置する。 ExampleElement という名前の要素のマージのディレクティブを選択します。
ユーザーがどのように生成されるかを EMD のコントロールはこのモデルでツールボックスからドラッグして新しい ExampleElement ついて説明します。たとえば
[ENT5ENT] ウィンドウで[入力] ENT6ENT を選択します。
ソリューションをビルドし直します。 これは生成されたコードをモデルから更新されるため通常は時間がかかります。
ビルド エラーは次のような報告されます : 「 Company.ElementMergeSample.ExampleElement 含まれません定義を… CanMergeExampleElement 」
メソッド CanMergeExampleElement を実装する必要があります。
*** Dsl *** プロジェクトの新しいコード ファイルを作成します。 次のコードの内容を置き換えプロジェクトの名前空間と名前空間を変更します。
using Microsoft.VisualStudio.Modeling; namespace Company.ElementMergeSample // EDIT. { partial class ExampleModel { /// <summary> /// Called whenever an ExampleElement is to be merged into this ExampleModel. /// This happens when the user pastes an ExampleElement /// or drags from the toolbox. /// Determines whether the merge is allowed. /// </summary> /// <param name="rootElement">The root element in the merging EGP.</param> /// <param name="elementGroupPrototype">The EGP that the user wants to merge.</param> /// <returns>True if the merge is allowed</returns> private bool CanMergeExampleElement(ProtoElementBase rootElement, ElementGroupPrototype elementGroupPrototype) { // Allow no more than 4 elements to be added: return this.Elements.Count < 4; } } }
この例では親のモデルにマージできる要素の数を制限します。 より重要な条件の場合メソッドはのプロパティに表示のリンクについて説明します。 またElementGroupPrototype 送信されるマージの要素のプロパティを調べることができます。 ElementGroupPrototypes の詳細については、「コピー動作のカスタマイズ」を参照してください。 モデルを読み込むコードを記述する方法の詳細についてはプログラム コードにおけるモデル内の移動およびモデルの更新 を参照してください。
DSL をテストする :
ソリューションをビルドし直すに F5 キーを押します。 Visual Studio の実験用インスタンスが開くとDSL のインスタンスを開きます。
いくつかの点で新しい要素を作成します :
図に ENT5ENT [入力] ツールをドラッグします。
*** Example Model Explorer *** でルート ノードを右クリックしを ENT9ENT [] をクリックします。
図の要素をコピーして貼り付けます。
モデルに 4 個以上の要素を追加するには次の方法を使用できないことを確認します。 これはそれらをすべて使用要素のマージのディレクティブです。
例 : マージ EMD にカスタム コードを追加できます。
カスタム マージ コードではユーザーがツールに要素をドラッグまたは貼り付けとどうなるかを定義できます。 カスタム定義をマージする方法が 2 つあります :
*** Uses Custom Merge *** を設定し必要なコードを指定します。 コードは生成されたコードをマージ置き換えます。 完全にマージできることを再定義する場合はこのオプションを使用します。
MergeRelate のメソッドおよびオプションで MergeDisconnect のメソッドをオーバーライドします。 これを行うにはドメイン クラス ENT4ENT [入力] プロパティを設定する必要があります。 コードは基本クラスの生成されたマージ コードを呼び出すことができます。 マージが発生した後に追加の操作を実行する場合はこのオプションを使用します。
これらの方法についてはこの EMD を使用してマージにのみ影響します。 マージされた要素を作成できるすべての方法に影響を与えようとする場合は代わりに埋め込みリレーションシップの AddRule およびマージされたドメイン クラス DeleteRule を定義します。 詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
MergeRelate をオーバーライドするには
DSL 定義ではコードを追加する EMD を定義することを確認します。 必要に応じてパスを追加し前のセクションで説明したようにカスタム コードを定義できます。
DslDefinition においてマージの受信するクラスを選択します。 通常埋め込みリレーションシップのソース端にクラスです。
たとえば最小限の言語のソリューションから生成される ExampleModelDSL のをクリックします。
[ENT1ENT] ウィンドウで***** true ***** に *** Generates Double Derived *** を設定します。
ソリューションをビルドし直します。
Dsl\Generated Files\DomainClasses.cs の内容を確認します。 MergeRelate という名前のメソッドを検索し内容を調べます。 これは固有のバージョンを作成できます。
新しいコード ファイルで受け取る側のクラスの部分クラスを作成しその MergeRelate のメソッドをオーバーライドします。 基本メソッドを呼び出すことに注意してください。 次に例を示します。
partial class ExampleModel { /// <summary> /// Called when the user drags or pastes an ExampleElement onto the diagram. /// Sets the time of day as the name. /// </summary> /// <param name="sourceElement">Element to be added</param> /// <param name="elementGroup">Elements to be merged</param> protected override void MergeRelate(ModelElement sourceElement, ElementGroup elementGroup) { // Connect the element according to the EMD: base.MergeRelate(sourceElement, elementGroup); // Custom actions: ExampleElement mergingElement = sourceElement as ExampleElement; if (mergingElement != null) { mergingElement.Name = DateTime.Now.ToLongTimeString(); } } }
マージ カスタム コードを作成するには
Dsl\Generated Code\DomainClasses.cs ではMergeRelate という名前のメソッドを確認します。 これらのメソッドは新しい要素と既存のモデル間のリンクを作成します。
またMergeDisconnect という名前のメソッドを確認します。 これらのメソッドは削除するときにモデル要素からのリンクを解除します。
*** DSL Explorer *** ではカスタマイズする要素のマージのディレクティブを選択または作成します。 [ENT1ENT] ウィンドウで***** Uses Custom Merge ***** を設定します。
このオプションをオンにすると***** Process Merge ***** と *** Forward Merge *** オプションは無視されます。 コードが使用されます。
ソリューションをビルドし直します。 これは生成されたコード ファイルがモデルから更新されるため通常は時間がかかります。
エラー メッセージが表示されます。 生成されたコードの命令を表示するエラー メッセージがダブルをクリックします。 これらの命令は 2 MergeRelateYourDomainClass メソッドおよび MergeDisconnectYourDomainClass を指定するように要求します
個別のコード ファイルの部分クラス定義のメソッドを記述します。 前の手順で確認した例に必要な情報を提案します。
カスタム マージ コードはオブジェクトとリレーションシップを作成する他の EMDs に影響を与えませんコードに影響しません。 要素がどのように関係なく作成するときに追加変更が実行されるようにするにはAddRule と DeleteRule のように記述することを検討してください。 詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
マージのリダイレクト
[マージのディレクティブはマージのターゲットをリダイレクトします。 通常新しいターゲットが開始ターゲットを埋め込む親です。
たとえばコンポーネント図のテンプレートで作成した DSL でポートをコンポーネントに埋め込まれます。 ポートをコンポーネント シェイプの末尾に図形として表示されます。 ユーザーはコンポーネント シェイプにポートのツールをドラッグしてポートを作成します。 ただしユーザーはコンポーネントではなく誤って既存のポートにポートのツールをドラッグし操作は失敗します。 これは既存のいくつかのポートがある場合に簡単な誤りです。 ユーザーがこの迷惑を回避するにはポートが既存のポートにドラッグしてからできますが親コンポーネントにリダイレクトするアクションがあります。 操作はターゲット要素がコンポーネントであるかのように動作します。
ソリューション構成モデルの前方マージのディレクティブを作成できます。 元のソリューションをコンパイルして実行するとユーザーが ツールボックス から コンポーネント の要素に *** Input Port *** または *** Output Port *** の任意の数の要素をドラッグできることが示されます。 ただし既存のポートにポートをドラッグすることはできません。 使用できないポインターはこの変換が有効になっていることを確認します。 ただし既存の *** Input Port *** で誤って削除ポートが コンポーネント の要素に転送するように順方向マージのディレクティブを作成できます。
[マージのディレクティブを作成するには
構成モデル テンプレートを使用して ドメイン固有言語ツール のソリューションを作成します。
DslDefinition.dsl を開いて***** DSL Explorer ***** が表示されます。
*** DSL Explorer *** ではENT3ENT を配置する。
*** ComponentPort *** のドメイン クラスは *** InPort *** と *** OutPort *** 両方の基本クラスです。 *** ComponentPort *** を右クリックしを ENT3ENT [] をクリックします。
新しい ENT8ENT [入力] ノードの ENT9ENT [入力] ノードの下に表示されます。
[入力] ENT3ENT ノードを選択し[ENT4ENT] ウィンドウを開きます。
インデックスのクラス ENT0ENT 一覧の [] を選択します。
[入力] ENT6ENT を選択します。
パスの選択リストでENT3ENT を展開しENT5ENT を展開し次に [入力] ENT7ENT を選択します。
新しいパスは次の 1 つになります。:
ComponentHasPorts.Component/! コンポーネント
ソリューションを保存しENT3ENT [入力] ツール バーの右端のボタンをクリックしてテンプレートを変換します。
ソリューションをビルドして実行します。 Visual Studio の新しいインスタンスが表示されます。
ソリューション エクスプローラー ではSample.mydsl を開きます。 図と *** ComponentLanguage Toolbox *** が表示されます。
ツールボックス から別の *** Input Port. *** にをドラッグ *** Input Port ***次に*** InputPort *** とは別の *** OutputPort *** に *** OutputPort *** をドラッグします。
使用できないポインターを表示し別に新しい *** Input Port *** を削除する必要があります。 新しい *** Input Port *** を選択し コンポーネント の別の位置にドラッグします。