Partilhar via


Atualizando formas e conectores para refletir o modelo

Em um idioma específico do domínio no Visual Studio, você pode fazer com que a aparência de uma forma refletem o estado do modelo subjacente.

Os exemplos de código neste tópico devem ser adicionados a uma .cs de arquivo em seu Dsl project.Essas instruções em cada arquivo será necessário:

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

Definir propriedades de mapa de forma para controlar a visibilidade do decorador

Você pode controlar a visibilidade do decorador sem escrever código de programa, configurando o mapeamento entre a forma e a classe de domínio na definição de DSL.Para obter mais informações, consulte os seguintes tópicos:

Expor a cor e o estilo de uma forma como propriedades

Na definição de DSL, clique com o botão direito a classe shape, aponte para Adicionar expostose então clique em um dos itens, como Cor de preenchimento.

A forma agora tem uma propriedade de domínio que você pode definir no código de programa ou como um usuário.Por exemplo, para defini-la no código de programa de um comando ou uma regra, você poderia escrever:

shape.FillColor = System.Drawing.Color.Red;

Se você desejar fazer a variável de propriedade somente sob o controle de programa e não por usuário, selecione a nova propriedade de domínio, como Cor de preenchimento no diagrama de definição de DSL.Em seguida, na janela Properties, defina É navegável para false ou definir É somente leitura de interface do usuário para true.

Definir regras de alteração para tornar a cor, estilo ou local dependem das propriedades do elemento de modelo

Você pode definir regras que atualizam a aparência da forma dependente de outras partes do modelo.Por exemplo, você poderia definir uma regra de alteração em um elemento de modelo que atualiza a cor da sua forma de acordo com as propriedades do elemento de modelo.Para obter mais informações sobre regras de alteração, consulte Regras de propagam alterações dentro do modelo.

Você deve usar regras apenas para atualizar as propriedades que são mantidas no armazenamento do arquivo, porque as regras não são chamadas quando o comando Desfazer é realizado.Isso não inclui alguns recursos gráficos como, por exemplo, o tamanho e a visibilidade de uma forma.Para atualizar esses recursos de uma forma, consulte recursos gráficos de armazenamento não atualizando.

O exemplo a seguir pressupõe que você tenha exposto FillColor como uma propriedade de domínio, conforme descrito na seção anterior.

[RuleOn(typeof(ExampleElement))]
  class ExampleElementPropertyRule : ChangeRule
  {
    public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
    {
      base.ElementPropertyChanged(e);
      ExampleElement element = e.ModelElement as ExampleElement;
      // The rule is called for every property that is updated.
      // Therefore, verify which property changed:
      if (e.DomainProperty.Id == ExampleElement.NameDomainPropertyId)
      {
        // There is usually only one shape:
        foreach (PresentationElement pel in PresentationViewsSubject.GetPresentation(element))
        {
          ExampleShape shape = pel as ExampleShape;
          // Replace this with a useful condition:
          shape.FillColor = element.Name.EndsWith("3") 
                     ? System.Drawing.Color.Red : System.Drawing.Color.Green;
        }
      }
    }
  }
  // The rule must be registered:
  public partial class OnAssociatedPropertyExptDomainModel
  {
    protected override Type[] GetCustomDomainModelTypes()
    {
      List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
      types.Add(typeof(ExampleElementPropertyRule));
      // If you add more rules, list them here. 
      return types.ToArray();
    }
  }

Use OnChildConfigured para inicializar as propriedades de uma forma

Para definir as propriedades de uma forma quando inicialmente criado, a substituição OnChildConfigured() em uma definição parcial da sua classe de diagrama.A classe de diagrama é especificada em sua definição de DSL e o código gerado está em Dsl\Generated Code\Diagram.cs.Por exemplo:

  partial class MyLanguageDiagram
  {
    protected override void OnChildConfigured(ShapeElement child, bool childWasPlaced, bool createdDuringViewFixup)
    {
      base.OnChildConfigured(child, childWasPlaced, createdDuringViewFixup);
      ExampleShape shape = child as ExampleShape;
      if (shape != null) 
      {
        if (!createdDuringViewFixup) return; // Ignore load from file.
        ExampleElement element = shape.ModelElement as ExampleElement;
        // Replace with a useful condition:
        shape.FillColor = element.Name.EndsWith("3") 
            ? System.Drawing.Color.Red : System.Drawing.Color.Green;
      }
      // else deal with other types of shapes and connectors.
    }
  }

Esse método pode ser usado para propriedades de domínio e não-armazenamento de recursos, como, por exemplo, o tamanho da forma.

Use o AssociateValueWith() para atualizar outros recursos de uma forma

Para alguns recursos de uma forma, como, por exemplo, se ele tem uma sombra, ou o estilo de seta de um conector, não há nenhum método incorporado de expor o recurso como uma propriedade de domínio.Alterações em tais recursos não estão sob o controle do sistema de transação.Portanto, não é apropriada para atualizá-los usando regras, porque as regras não são chamadas quando o usuário executa o comando Desfazer.

Em vez disso, você pode atualizar recursos, usando OnAssociatedPropertyChanged.No exemplo a seguir, o estilo de seta de um conector é controlado por um valor de uma propriedade de domínio na relação que o conector exibe:

public partial class ArrowConnector // My connector class. 
{
   /// <summary>
    /// Called whenever a registered property changes in the associated model element.
    /// </summary>
    /// <param name="e"></param>
    protected override void OnAssociatedPropertyChanged(VisualStudio.Modeling.Diagrams.PropertyChangedEventArgs e)
    {
      base.OnAssociatedPropertyChanged(e);
      // Can be called for any property change. Therefore,
      // Verify that this is the property we're interested in:
      if ("IsDirected".Equals(e.PropertyName))
      {
        if (e.NewValue.Equals(true))
        { // Update the shape’s built-in Decorator feature:
          this.DecoratorTo = LinkDecorator.DecoratorEmptyArrow;
        }
        else
        {
          this.DecoratorTo = null; // No arrowhead.
        }
      }
    }
    // OnAssociatedPropertyChanged is called only for properties
    // that have been registered using AssociateValueWith().
    // InitializeResources is a convenient place to call this.
    // This method is invoked only once per class, even though
    // it is an instance method. 
    protected override void InitializeResources(StyleSet classStyleSet)
    {
      base.InitializeResources(classStyleSet);
      AssociateValueWith(this.Store, Wire.IsDirectedDomainPropertyId);
      // Add other properties here.
    }
} 

AssociateValueWith()deve ser chamado uma vez para cada propriedade de domínio que você deseja registrar.Depois que tiver sido chamado, quaisquer alterações para a propriedade especificada chamará OnAssociatedPropertyChanged() em quaisquer formas que apresentam o elemento de modelo da propriedade.

Não é necessário chamar AssociateValueWith() para cada instância.Embora o InitializeResources é um método de instância, ele é chamado somente uma vez para cada classe de forma.