域属性值更改处理程序

在 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 在关系类。 ,当链接已创建或已更改时,这些规则会触发。 有关更多信息,请参见规则在模型内部传播更改

Bb126481.collapse_all(zh-cn,VS.110).gif和存储的更改

属性处理程序方法调用开始更改的事务内。 因此,可以将多个更改。存储,而不必打开新事务。 更改可能会导致额外的处理程序。

在事务中移除,都会重新提交或回滚时,不应更改在存储,也就是说,对模型元素、关系、形状、连接关系图,或其属性的更改。

此外,在中,当模型从文件时,加载您通常不会更新值。

应由如下一测试控制对该模型的因此更改:

if (!store.InUndoRedoOrRollback 
         && !store. InSerializationTransaction)
{ this.TextLength = ...; // in-store changes 
}

相反,因此,如果属性处理程序在存储外传播更改,例如,某个文件,数据库或非存储变量,然后应始终进行一些更改,以便外部值更新,当用户调用撤消或重做时。

Bb126481.collapse_all(zh-cn,VS.110).gif撤消更改

如果希望阻止更改,可以回滚当前事务。 例如,您可能希望确保属性在指定范围内保持。

if (newValue > 10) 
{ store.TransactionManager.CurrentTransaction.Rollback();
  System.Windows.Forms.MessageBox.Show("Value must be less than 10");
} 

Bb126481.collapse_all(zh-cn,VS.110).gif备选方法:计算的属性

前面示例中演示 OnValueChanged() 如何使用传播一个字段特性的值更改为另一个。 每个属性都有自己的单元的值。

相反,可考虑定义该 " 属性作为一个计算的属性。 在这种情况下,属性没有自己的存储和定义函数进行求值,当需要其值。 有关更多信息,请参见 计算的和自定义的存储属性

而不是上面的示例,您可以设置 TextLengthCount 的 kind 字段是在 DSL 定义的 计算 。 您会提供拥有 获取 方法此字段的特性。 获取 方法将返回 文本 字符串中的当前长度。

但是,计算的属性一个潜在缺点是该表达式每次计算值使用,可能存在性能问题。 而且,如果没有 OnValueChanging() 和 OnValueChanged() 在一个计算的属性。

Bb126481.collapse_all(zh-cn,VS.110).gif备选方法:更改规则

如果定义 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) }; 
 }
} 

示例

Bb126481.collapse_all(zh-cn,VS.110).gif说明

,当 ExampleElement 域类的属性更改时,下面的示例重写字段的特性的属性处理程序并通知用户。

Bb126481.collapse_all(zh-cn,VS.110).gif代码

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);
      }
    }
  }
}

请参见

参考

OnValueChanged

OnValueChanging