Compartilhar via


Navegando e atualizando um modelo de código de programa

Você pode escrever código para criar e excluir elementos modelo, para definir suas propriedades, e para criar e excluir links entre elementos.Todas as alterações devem ser feita dentro de uma transação.Se os elementos são exibidos em um diagrama, o diagrama anterior” corrigido “será automaticamente no final da transação.

Em este tópico

Uma definição de DSL de exemplo

navegando no modelo

Acessando informações de classe

Fazer alterações em uma transação

Criando elementos modelo

Criando links de relação

Excluindo elementos

Excluindo links de relação

Reorganizando links de uma relação

bloqueios

Impressão e pasta

navegando em e atualizando diagramas

Navegar entre elementos e formas

Propriedades de formas e os conectores

DocView e DocData

As formas, os conectores e os diagramas, e suas relações elementos modelo são descritos em um tópico separado.Para obter mais informações, consulte [redirecionar] Como: navegar e atualizar um diagrama..

Uma definição de DSL de exemplo

Essa é a parte principal de DslDefinition.dsl para os exemplos em este tópico:

Diagrama de definição de DSL - modelo de árvore genealógica

Esse modelo é uma instância de esse DSL:

Modelo de árvore da família Tudor

Cc512845.collapse_all(pt-br,VS.110).gifreferências e namespaces

Para executar o código em este tópico, você deve referenciar:

Microsoft.VisualStudio.Modeling.Sdk.11.0.dll

Seu código usará este namespace:

using Microsoft.VisualStudio.Modeling;

Além de isso, se você estiver escrevendo código em um projeto diferente do que em seu DSL é definido, você deve importar o assembly que é compilado pelo projeto de Dsl.

Cc512845.collapse_all(pt-br,VS.110).gifPropriedades

As propriedades de domínio que você define na definição de DSL tornam-se as propriedades que você pode acessar no código de programa:

Person henry = ...;

if (henry.BirthDate < 1500) ...

if (henry.Name.EndsWith("VIII")) ...

Se você desejar definir uma propriedade, você deve fazê-lo dentro de transação:

henry.Name = "Henry VIII";

Se a definição de DSL, Tipo de uma propriedade é Calculado, você não pode defini-la.Para obter mais informações, consulte Propriedades de armazenamento de calculado e personalizadas.

Cc512845.collapse_all(pt-br,VS.110).gifrelações

Os relacionamentos de domínio que você define na definição de DSL tornam-se pares de propriedades, em uma classe em cada final da relação.Os nomes das propriedades aparecem no diagrama de DslDefinition como rótulos funções em cada lado da relação.Dependendo da função, multiplicidade do tipo da propriedade é a classe no outro extremo de relação, ou uma coleção da classe.

foreach (Person child in henry.Children) { ... }

FamilyTreeModel ftree = henry.FamilyTreeModel;

as propriedades em extremos opostos de uma relação são sempre recíprocas.Quando um link é criado ou excluído, as propriedades em ambos os elementos é atualizada.A seguinte expressão (usando as extensões de System.Linq) é sempre true para a relação de ParentsHaveChildren no exemplo:

(Person p) => p.Children.All(child => child.Parents.Contains(p))

&& p.Parents.All(parent => parent.Children.Contains(p));

ElementLinks.Um relacionamento é representada por um elemento modelo também chamado um link, que é uma instância do tipo do relacionamento de domínio.Um link sempre tem um elemento de origem e um elemento de destino.O elemento de origem e o elemento alvo podem ser o mesmo.

você pode acessar um link e suas propriedades:

ParentsHaveChildren link = ParentsHaveChildren.GetLink(henry, edward);

// This is now true:

link == null || link.Parent == henry && link.Child == edward

Por padrão, não é permitida mais de uma instância de uma relação vincular todos os pares de elementos modelo.Mas se a definição de DSL, o sinalizador de Allow Duplicates é verdadeiro para o relacionamento em seguida, pode haver mais de um link, e você deve usar GetLinks:

foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinks(henry, edward)) { ... }

Há também outros métodos para acessar os links.Por exemplo:

foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinksToChildren(henry)) { ... }

funções ocultos. Se a definição de DSL, A propriedade é gerada é false para uma função específica, então nenhuma propriedade é gerada que corresponde à função.Em o entanto, você ainda pode acessar os links e a travessia links usando os métodos de relação:

foreach (Person p in ParentsHaveChildren.GetChildren(henry)) { ... }

Mais geralmente o exemplo usado é o relacionamento de PresentationViewsSubject , que referencia um elemento modelo a forma que exibe em um diagrama:

PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape

Cc512845.collapse_all(pt-br,VS.110).gifO diretório de elemento

Você pode acessar todos os elementos no armazenamento usando o diretório do elemento:

store.ElementDirectory.AllElements

Há também métodos para localizar elementos, como o seguinte:

store.ElementDirectory.FindElements(Person.DomainClassId);

store.ElementDirectory.GetElement(elementId);

Acessando informações de classe

Você pode obter informações sobre classes, relacionamentos, e outros aspectos da definição de DSL.Por exemplo:

DomainClassInfo personClass = henry.GetDomainClass();

DomainPropertyInfo birthProperty =

personClass.FindDomainProperty("BirthDate")

DomainRelationshipInfo relationship =

link.GetDomainRelationship();

DomainRoleInfo sourceRole = relationship.DomainRole[0];

As classes de ancestral de elementos modelo são:

  • ModelElement - todos os elementos e relações são ModelElements

  • ElementLink - todas as relações são ElementLinks

Fazer alterações em uma transação

Sempre que o código de programa altera qualquer coisa no armazenamento, deve fazê-lo dentro de uma transação.Isso se aplica a todos os elementos modelo, a relações, como formas, como diagramas, e suas propriedades.Para obter mais informações, consulte Transaction.

O método mais conveniente de gerenciar uma transação é com uma instrução de using incluída em uma instrução de try...catch :

Store store; ...
try
{
  using (Transaction transaction =
    store.TransactionManager.BeginTransaction("update model"))
    // Outermost transaction must always have a name.
  {
    // Make several changes in Store:
    Person p = new Person(store);
    p.FamilyTreeModel = familyTree;
    p.Name = "Edward VI";
    // end of changes to Store

    transaction.Commit(); // Don't forget this!
  } // transaction disposed here
}
catch (Exception ex)
{
  // If an exception occurs, the Store will be 
  // rolled back to its previous state.
}

Você pode fazer qualquer número de alterações dentro de uma transação.Você pode abrir novos transações dentro de uma transação.

Para tornar seu permanent as alterações, você deve Commit a transação antes de ser descartado.Se ocorrer uma exceção que não sejam capturadas na transações, o armazenamento será redefinido em seu estado antes de alterações.

Criando elementos modelo

este exemplo adiciona um elemento a um modelo existente:

FamilyTreeModel familyTree = ...; // The root of the model.       
using (Transaction t =
    familyTree.Store.TransactionManager
    .BeginTransaction("update model"))
{
  // Create a new model element 
  // in the same partition as the model root:
  Person edward = new Person(familyTree.Partition);
  // Set its embedding relationship:
  edward.FamilyTreeModel = familyTree;
          // same as: familyTree.People.Add(edward);
  // Set its properties:
  edward.Name = "Edward VII";
  t.Commit(); // Don't forget this!
}

Este exemplo ilustra esses pontos essenciais sobre a criação de um elemento:

  • Crie o novo elemento em uma partição específico de armazenamento.Para elementos e relacionamentos modelo, mas não formas, isso é geralmente o partição padrão.

  • Torna o destino de uma relação inseridas.Em o DslDefinition de este exemplo, cada pessoa deve ser o destino da relação FamilyTreeHasPeople inseridas.Para obter isso, podemos ou definir a função da propriedade de FamilyTreeModel do objeto da pessoa, ou adicione a pessoa à função de propriedade de pessoas do objeto de FamilyTreeModel.

  • Definir as propriedades de um novo elemento, especialmente a propriedade para que IsName é verdadeira no DslDefinition.Este sinalizador marca a propriedade que serve para identificar exclusivamente o elemento dentro do proprietário.Em esse caso, a propriedade name tem esse sinalizador.

  • A definição de DSL de este DSL deve ter sido carregadas no armazenamento.Se você estiver escrevendo uma extensão como um comando de menu, este será normalmente já true.Em outros casos, você pode explicitamente carregar o modelo no armazenamento, ou use ModelBus para carregá-lo.Para obter mais informações, consulte Como: abrir um modelo de arquivo no código de programa.

Quando você cria um elemento de essa maneira, uma forma é criada automaticamente (se DSL tem um diagrama).Aparece em um local automaticamente atribuído, a maneira padrão, cor, e outros recursos.Se você deseja controlar como e onde a forma associado for exibida, consulte criando um elemento e sua forma.

Há duas relações definidas na definição de DSL de exemplo.Cada relacionamento define uma função da propriedade na classe em cada final da relação.

Existem três maneiras em que você pode criar uma instância de um relacionamento.Cada um de esses três métodos tem o mesmo efeito:

  • Defina a propriedade da função de jogador de origem.Por exemplo:

    • familyTree.People.Add(edward);

    • edward.Parents.Add(henry);

  • Defina a propriedade da função de jogador de destino.Por exemplo:

    • edward.familyTreeModel = familyTree;

      A multiplicidade de essa função é 1..1, de forma que é atribuímos o valor.

    • henry.Children.Add(edward);

      A multiplicidade de essa função é 0..*, o que nós adicionados à coleção.

  • Crie uma instância de relação explicitamente.Por exemplo:

    • FamilyTreeHasPeople edwardLink = new FamilyTreeHasPeople(familyTreeModel, edward);

    • ParentsHaveChildren edwardHenryLink = new ParentsHaveChildren(henry, edward);

O método do último é útil se você desejar definir as propriedades da relação próprias.

Quando você cria um elemento de essa maneira, um conector no diagrama é criado automaticamente, mas tem uma maneira padrão, a cor, e outros recursos.Para controlar como o conector associado é criado, consulte criando um elemento e sua forma.

Excluindo elementos

excluir um elemento chamando Delete():

henry.Delete();

Esta operação também excluirá:

  • Links de relação a e do elemento.Por exemplo, edward.Parents não conterá henry.

  • Elementos nas funções para que o sinalizador de PropagatesDelete é válido.por exemplo, a forma que exibe o elemento será excluída.

Por padrão, cada relacionamento inseridas tem PropagatesDelete verdadeiro na função de destino.Excluindo henry não exclui familyTree, mas familyTree.Delete() excluiria qualquer Persons.Para obter mais informações, consulte Personalizar o comportamento de exclusão.

Por padrão, PropagatesDelete não é verdadeiro para as funções de relações de referência.

Você pode fazer com que as regras de exclusão omitam se propaga específicas quando você exclui um objeto.Isso é útil se você está substituindo um elemento para outro.Você fornece um GUID de uma ou mais funções para que a exclusão não deve ser propagada.Um GUID pode ser obtido da classe de relação:

henry.Delete(ParentsHaveChildren.SourceDomainRoleId);

(Esse exemplo específico não terá efeito, porque PropagatesDelete é false para as funções da relação ParentsHaveChildren .)

Em alguns casos, a exclusão é impedida pela existência de um bloqueio, no elemento ou um elemento que é excluído. por bolhavocê pode usar element.CanDelete() para verificar se o elemento possa ser excluído.

Você pode excluir um link de relação remover um elemento de uma função da propriedade:

henry.Children.Remove(edward); // or:

edward.Parents.Remove(henry); // or:

Você também pode excluir o link explicitamente:

edwardHenryLink.Delete();

Todos esses três métodos têm o mesmo efeito.Você só precisará usar um de eles.

Se a função tem a multiplicidade 0..1 ou 1..1, você pode defini-la a null, ou para outro valor:

edward.FamilyTreeModel = null; ou //:

edward.FamilyTreeModel = anotherFamilyTree;

Links de uma relação específico que são originários ou de destino em um elemento do modelo de detalhe têm uma seqüência específica.Aparecem na ordem em que foram adicionados.Por exemplo, essa instrução sempre renderá os filhos na mesma ordem:

foreach (Person child in henry.Children) ...

Você pode alterar a ordem dos links:

ParentsHaveChildren link = GetLink(henry,edward);

ParentsHaveChildren nextLink = GetLink(henry, elizabeth);

DomainRoleInfo role =

link.GetDomainRelationship().DomainRoles[0];

link.MoveBefore(role, nextLink);

bloqueios

Suas alterações podem ser evitadas por um bloqueio.Os bloqueios podem ser definidas em elementos individuais, e em particiona no armazenamento.Se qualquer um dos níveis têm um bloqueio que evitasse o tipo de alteração que você deseja fazer, uma exceção pode ser lançada quando você tentar a.Você pode descobrir se os bloqueios são definidos usando element.GetLocks(), que é um método de extensão que é definido no namespace Microsoft.VisualStudio.Modeling.Immutability.

Para obter mais informações, consulte Definir uma diretiva de bloqueio para criar segmentos de somente leitura.

Impressão e pasta

Você pode copiar os elementos ou grupos de elementos a IDataObject:

Person person = personShape.ModelElement as Person;
Person adopter = adopterShape.ModelElement as Person;
IDataObject data = new DataObject();
personShape.Diagram.ElementOperations
      .Copy(data, person.Children.ToList<ModelElement>());

Os elementos são armazenados como um grupo serializada do elemento.

você pode mesclar os elementos de um IDataObject em um modelo:

using (Transaction t = targetDiagram.Store.
        TransactionManager.BeginTransaction("paste"))
{
  adopterShape.Diagram.ElementOperations.Merge(adopter, data);
}

Merge () pode aceitar PresentationElement ou ModelElement.Se você fornece PresentationElement, você também pode especificar uma posição no diagrama de destino como um terceiro parâmetro.

Em DSL, o elemento modelo de domínio, que representa um conceito como a pessoa ou a música, é separado do elemento, de forma que representa o que você vê no diagrama.O elemento do modelo de domínio armazena as propriedades e relacionamentos importantes conceitos.O elemento de forma armazena o tamanho, posição e cor do modo de objeto no diagrama, e o layout de seus elementos.

Cc512845.collapse_all(pt-br,VS.110).gifElementos de apresentação

Diagrama de classes de tipos de forma e o elemento base

Em sua definição de DSL, cada elemento que você especifica cria uma classe que é derivada de uma das seguintes classes padrão.

Tipo de elemento

classe base

Classe de domínio

ModelElement

relacionamento de domínio

ElementLink

forma

NodeShape

conector

BinaryLinkShape

Diagrama

Diagram

Um elemento em um diagrama geralmente representa um elemento modelo.Normalmente (mas não sempre), NodeShape representa uma instância da classe de domínio, e BinaryLinkShape representa uma instância do relacionamento de domínio.A relação de PresentationViewsSubject links uma forma de um nó ou de link para o elemento que representa modelo.

Cada forma de um nó ou de link pertence a um diagrama.Uma forma binária de link conecta duas formas do nó.

As formas podem ter formas filho em dois conjuntos.Uma forma em NestedChildShapes definido é limitada a caixa delimitadora de seu pai.Uma forma na lista de RelativeChildShapes pode aparecer fora ou em lugar fora dos limites do pai – por exemplo um rótulo ou uma porta.Um diagrama não tem RelativeChildShapes e nenhum Parent.

Cc512845.collapse_all(pt-br,VS.110).gifNavegar entre elementos e formas

Elementos modelo de domínio e elementos de forma são relacionados a relação de PresentationViewsSubject .

// using Microsoft.VisualStudio.Modeling;
// using Microsoft.VisualStudio.Modeling.Diagrams;
// using System.Linq;
Person henry = ...;
PersonShape henryShape = 
  PresentationViewsSubject.GetPresentation(henry)
    .FirstOrDefault() as PersonShape;

A mesma relação aos conectores são relacionamentos no diagrama:

Descendants link = Descendants.GetLink(henry, edward);
DescendantConnector dc =
   PresentationViewsSubject.GetPresentation(link)
     .FirstOrDefault() as DescendantConnector;
// dc.FromShape == henryShape && dc.ToShape == edwardShape

Esse relacionamento também ajudam a raiz do modelo ao diagrama a seguir:

FamilyTreeDiagram diagram = 
   PresentationViewsSubject.GetPresentation(familyTree)
      .FirstOrDefault() as FamilyTreeDiagram;

para obter o elemento modelo representado por uma forma, use:

henryShape.ModelElement as Person

diagram.ModelElement as FamilyTreeModel

Cc512845.collapse_all(pt-br,VS.110).gifNavegue em torno do diagrama

Em geral não é aconselhável navegar entre formas e conectores no diagrama.É melhor navegar nas relações no modelo, mover entre as formas e os conectores somente quando for necessário trabalhar na aparência do diagrama.Esses métodos vinculam conectores para desenhar formas em cada final:

personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes

connector.FromShape, connector.ToShape

muitas formas são composições; são compostos de uma forma pai e de uma ou mais camadas de filhos.As formas que são identificadas em relação a outra forma seria seus filhos.Quando o formulário pai se move, os filhos se movem com ele.

Os filhos relacionados podem aparecer fora da caixa delimitadora de forma pai.Os filhosaninhados estritamente aparecem nos limites do pai.

para obter o conjunto superior de formas em um diagrama, use:

Diagram.NestedChildShapes

As classes de ancestral de formas e de conectores são:

ModelElement

-- PresentationElement

-- ShapeElement

----- NodeShape

------- Diagram

------- YourShape

----- LinkShape

------- BinaryLinkShape

--------- YourConnector

Cc512845.collapse_all(pt-br,VS.110).gifPropriedades de formas e os conectores

Em a maioria dos casos, não é necessário fazer alterações explícitas para desenhar formas.Quando você alterou os elementos modelo, “corrigir anterior” regras atualizar as formas e os conectores.Para obter mais informações, consulte Respondendo a e propagação de alterações.

Em o entanto, é útil fazer algumas alterações explícitas para desenhar formas nas propriedades que são independentes de elementos modelo.Por exemplo, você pode alterar essas propriedades:

  • Size - determina a altura e largura da forma.

  • Location - posição relativa à forma ou ao diagrama pai

  • StyleSet - o conjunto de menus e pincéis usado desenhando a forma ou o conector

  • Hide - faz a forma invisível

  • Show - faz a forma visível após Hide()

Cc512845.collapse_all(pt-br,VS.110).gifcriando um elemento e sua forma

Quando você cria um elemento e o links na árvore de relações de uma forma automaticamente, inserindo é criada e associada a ela.Isso é feito pelas regras de “fixup” que executam no final da transação.Em o entanto, o formulário será exibido em um local automaticamente- atribuído, e sua forma, a cor e outros recursos terão valores padrão.Para controlar como a forma é criada, você pode usar a função de mesclagem.Você deve primeiro adicionar elementos que você deseja adicionar em um ElementGroup, e mescla no grupo no diagrama.

este método:

  • Defina o nome, se você tiver atribuído uma propriedade como o nome do elemento.

  • Notas todas as políticas de mesclagem do elemento que você especifique na definição de DSL.

Este exemplo cria uma forma na posição do mouse, quando o usuário clica duas vezes no diagrama.Em a definição de DSL para esse exemplo, a propriedade de FillColor de ExampleShape foi expostas.

  using Microsoft.VisualStudio.Modeling;
  using Microsoft.VisualStudio.Modeling.Diagrams;
  partial class MyDiagram
  {
    public override void OnDoubleClick(DiagramPointEventArgs e)
    {
      base.OnDoubleClick(e);

      using (Transaction t = this.Store.TransactionManager
          .BeginTransaction("double click"))
      {
        ExampleElement element = new ExampleElement(this.Store);
        ElementGroup group = new ElementGroup(element);
         
        { // To use a shape of a default size and color, omit this block.
          ExampleShape shape = new ExampleShape(this.Partition);
          shape.ModelElement = element;
          shape.AbsoluteBounds = new RectangleD(0, 0, 1.5, 1.0);
          shape.FillColor = System.Drawing.Color.Azure;
          group.Add(shape);
        }

        this.ElementOperations.MergeElementGroupPrototype(
          this,
          group.CreatePrototype(),
          PointD.ToPointF(e.MousePosition));
        t.Commit();
      }
    }
  }

Se você fornecer mais de uma forma, definir suas posições relacionados usando AbsoluteBounds.

Você também pode definir a cor e outras propriedades expostas dos conectores usando esse método.

Cc512845.collapse_all(pt-br,VS.110).gifuse transações

As formas, os conectores e os diagramas são subtipos de ModelElement e vivem no armazenamento.Portanto você deve fazer alterações em eles apenas dentro de uma transação.Para obter mais informações, consulte Como: usar transações para atualizar o modelo.

Modo de exibição de documento e dados de documento

Diagrama de classes de tipos de diagrama padrão

Particiona armazenamento de

Quando um modelo é carregado, o diagrama de rastreamento é carregado ao mesmo tempo.Normalmente, o modelo é carregado em Store.DefaultPartition, e o conteúdo do diagrama é carregado em outra partição.Geralmente, o conteúdo de cada partição é carregado e salvo em um arquivo separado.

Consulte também

Referência

ModelElement

Conceitos

Validação em um idioma específico do domínio

Como: usar transações para atualizar o modelo

A integração de modelos usando o Modelbus de Visual Studio

Outros recursos

Gerando código a partir de uma linguagem específica de domínio

Respondendo a e propagação de alterações