網域屬性值變更處理常式
在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");
}
另一個技術: 計算屬性
先前的範例會示範如何使用 「 OnValueChanged() 」 傳播到另一個網域屬性值。每個屬性都有它自己的儲存的值。
相反地,您可以考慮為計算的屬性定義衍生的屬性。情況下,屬性有它自己,沒有儲存,就要定義其值,必要時,被評估函式。如需詳細資訊,請參閱 計算及自訂的儲存區屬性。
代替先前的範例中,您可以設定類 欄位的 TextLengthCount 是計算 DSL 定義中。會提供您自己取得這個定義域屬性的方法。取得 方法會傳回的目前長度 文字的字串。
不過,計算內容的潛在的缺點是會評估運算式,每次使用值,這可能會出現效能問題。此外,就不會有 OnValueChanging() 和 OnValueChanged() 上計算的屬性。
另一個技術: 變更規則
如果您定義的 ChangeRule,它會執行最後的交易,在其中變更屬性的值。如需詳細資訊,請參閱規則傳播模型內的變更。
如果在一個交易中做了多項變更,當它們都已全部完成,也會執行 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) };
}
}
範例
描述
下列範例會覆寫網域屬性的屬性處理常式,並通知使用者時的屬性, 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);
}
}
}
}