域属性值更改处理程序
在 Visual Studio 域特定语言,那么,当字段的特性的值发生更改时, OnValueChanging() 和 OnValueChanged() 方法在字段的特性处理程序调用。 若要响应更改,则可以重写这些方法。
重写属性处理程序方法
该域特定语言 (dsl) 每个字段特性由嵌套在其父域类中的类处理。 其名称遵循以下格式 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 的 kind 字段是在 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);
}
}
}
}