ドメイン プロパティ値変更ハンドラー
Visual Studio のドメインはドメイン固有言語でのプロパティの値および OnValueChanging()OnValueChanged() のメソッドがドメインのプロパティ ハンドラーで開始されます。変更に応答するにはこれらのメソッドをオーバーライドします。
プロパティのハンドラー メソッドのオーバーライド
ドメイン固有言語の各プロパティは親ドメインのドメインにクラスの中に入れ子になったクラスによって処理されます。この名前は PropertyNamePropertyHandler 形式に従います。ファイル Dsl\Generated Code\DomainClasses.cs このハンドラー クラスのプロパティを調べることができます。クラスではOnValueChanging() は値が変更した直後に値が変更されたときOnValueChanged() が呼び出される直前に呼び出されます。
たとえば コメント という名前の文字列のドメイン プロパティによって指定される テキスト と TextLengthCount という整数のプロパティを持つドメイン クラスがあるとします。TextLengthCount は テキスト 文字列の長さがあります。常にDsl プロジェクトに個別のファイルに次のコードを記述する場合 :
// Domain Class "Comment":
public partial class Comment
{
// Domain Property "Text":
partial class TextPropertyHandler
{
protected override void OnValueChanging(CommentBase element, string oldValue, string newValue)
{
base.OnValueChanging(element, oldValue, newValue);
// To update values outside the Store, write code here.
// Let the transaction manager handle undo:
Store store = element.Store;
if (store.InUndoRedoOrRollback || store.InSerializationTransaction) return;
// Update values in the Store:
this.TextLengthCount = newValue.Length;
}
}
}
プロパティ ハンドラーについては次の点に注意してください :
プロパティのハンドラー メソッドはプロパティにユーザーのドメインのプロパティを変更するとプログラム コード値を割り当てるときに呼び出されます。
メソッドは値が実際に変更した場合にのみ呼び出されます。ハンドラーはプログラム コードが現在の値と同じ値を割り当てる呼び出されません。
計算されたカスタム ストレージのドメインのプロパティに OnValueChanged と OnValueChanging のメソッドがありません。
新しい値の変更によってハンドラーを使用できません。たとえば特定のスコープに値を制限するにはChangeRule を定義するする場合は。
関係のロールを表すプロパティによってハンドラーを追加することはできません。代わりにクラスの関係 AddRule と DeleteRule を定義します。これらの規則はリンクを作成または変更されたときに発生します。詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
ストアに出入りする変更
ハンドラー メソッドがプロパティの変更を開始したトランザクション内で呼び出されます。したがって新しいトランザクションを開かずに関する詳細に変更を加えることができます。変更は追加のハンドラーの呼び出しで発生する場合があります。
トランザクションを元に戻すまたはやり直しされたまたはロールバックするとストア内の変更モデル要素関係図形コネクタの図またはプロパティにつまり変更する必要はありません。
またモデルがファイルから読み込まれているとき通常の値を更新。
したがってモデルへの変更はテストで保護する必要があります :
if (!store.InUndoRedoOrRollback
&& !store. InSerializationTransaction)
{ this.TextLength = ...; // in-store changes
}
一方によってプロパティがハンドラー ストアの外部での変更はデータベース ファイルに非ストアの変数反映させる場合はユーザーが戻す操作またはやり直し操作を開始する場合外部値を更新するようにこれらの変更を常に行う必要があります。
変更をキャンセル
変更を永続的に禁止する場合はロールバック現在のトランザクションができます。たとえばプロパティが特定の範囲内にあることを確認する必要がある場合があります。
if (newValue > 10)
{ store.TransactionManager.CurrentTransaction.Rollback();
System.Windows.Forms.MessageBox.Show("Value must be less than 10");
}
代替方法 : 計算されたプロパティ
前の例では1 種類のドメインのプロパティから別の状態に値を反映させるために OnValueChanged () を使用する方法を示します。独自の各プロパティに格納されている値があります。
代わりに計算されたプロパティと派生プロパティを定義することもできます。その場合は値が必要なときにプロパティに独自のストレージはなく関数を定義して評価されます。詳細については、「計算プロパティおよびカスタム格納プロパティ」を参照してください。
前の例ではなくDSL の定義 *** Calculated *** に TextLengthCount の ENT0ENT [入力] フィールドで設定できます。このドメインのプロパティに 取得 に独自のメソッドを提供します。 取得 のメソッドは テキスト の文字列の現在の長さを返します。
ただし計算されたプロパティの短所と式が値パフォーマンスの問題を示す使用されるたびに評価することです。またOnValueChanging () と計算したプロパティに OnValueChanged () がありません。
代替方法 : 規則の変更
ChangeRule を定義すると属性値が変更されるトランザクションの最後に実行されます。詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
1 回のトランザクション複数の変更が行われるとChangeRule はすべて完了したときに実行されます。対照的にOnValue …メソッドは変更の一部が来ていない場合は実行されます。実行するタスクによってはこれは ChangeRule を適切に行うことがあります。
特定の範囲内に保持するプロパティの新しい値を調整するために ChangeRule を使用できます。
注意 |
---|
規則がストアのコンテンツを変更した場合他の規則およびプロパティ ハンドラーがトリガーされることがあります。規則が発生したプロパティを変更すると再び呼び出しています。規則の定義が無限のトリガーがないことを確認する必要があります。 |
using Microsoft.VisualStudio.Modeling;
...
// Change rule on the domain class Comment:
[RuleOn(typeof(Comment), FireTime = TimeToFire.TopLevelCommit)]
class MyCommentTrimRule : ChangeRule
{
public override void
ElementPropertyChanged(ElementPropertyChangedEventArgs e)
{
base.ElementPropertyChanged(e);
Comment comment = e.ModelElement as Comment;
if (comment.Text.StartsWith(" ") || comment.Text.EndsWith(" "))
comment.Text = comment.Text.Trim();
// If changed, rule will trigger again.
}
}
// Register the rule:
public partial class MyDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{ return new Type[] { typeof(MyCommentTrimRule) };
}
}
例
Description
次の例では ExampleElement のドメイン クラスのプロパティが変更されているドメインのプロパティ ハンドラーをオーバーライドしユーザーに通知します。
コード
using DslModeling = global::Microsoft.VisualStudio.Modeling;
using DslDesign = global::Microsoft.VisualStudio.Modeling.Design;
namespace msft.FieldChangeSample
{
public partial class ExampleElement
{
internal sealed partial class NamePropertyHandler
{
protected override void OnValueChanged(ExampleElement element,
string oldValue, string newValue)
{
if (!this.Store.InUndoRedoOrRollback)
{
// make in-store changes here...
}
// This part is called even in undo:
System.Windows.Forms.MessageBox.Show("Value Has Changed");
base.OnValueChanged(element, oldValue, newValue);
}
}
}
}