Udostępnij za pośrednictwem


Nawigowanie i aktualizowanie modelu w kodzie programu

Można napisać kod tworzenie i usuwanie elementów modelu, ustawiać ich właściwości oraz tworzenie i usuwanie łącza między elementami.Wszystkie zmiany należy wprowadzać w obrębie transakcji.Jeśli elementy są wyświetlane na diagramie, diagram będzie "ustalana" automatycznie po zakończeniu transakcji.

W tym temacie

W przypadku definicji DSL przykład

Nawigacja modelu

Dostęp do informacji, klasa

Wykonać zmiany wewnątrz transakcji

Tworzenie elementów modelu

Tworzenie relacji łącza

Usuwanie elementów

Usuwanie łącza relacji

Zmienianie kolejności łączy relacji

Blokuje

Kopiowanie i wklejanie

Przeglądanie i aktualizowanie diagramów

Przechodzenie między kształtami i elementy

Właściwości kształtów i łączników

DocView i DocData

W oddzielnym temacie opisano kształtów, łączniki i schematów oraz ich relacje z elementami modelu.Aby uzyskać więcej informacji, zobacz [redirect] — Porady: diagram — aktualizacja i nawigowanie.

W przypadku definicji DSL przykład

Jest to główna część DslDefinition.dsl w przykładach w tym temacie:

Diagram DSL Definition - model drzewa rodziny

Ten model jest wystąpienie tego DSL:

Model drzewa rodziny Tudorów

Odwołania i przestrzenie nazw

Aby uruchomić kod w tym temacie, należy odwołać:

Microsoft.VisualStudio.Modeling.Sdk.11.0.dll

Kod będzie używać tego obszaru nazw:

using Microsoft.VisualStudio.Modeling;

Ponadto pisania kodu z innego projektu, niż ten, w którym zdefiniowano modem DSL, należy zaimportować zestaw, który jest zbudowany przez program project Dsl.

Nawigacja modelu

Właściwości

Właściwości domeny, które można zdefiniować w definicji DSL stają się właściwości, które można uzyskać dostęp w kod programu:

Person henry = ...;

if (henry.BirthDate < 1500) ...

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

Jeśli chcesz ustawić właściwość, należy to zrobić wewnątrz transakcji:

henry.Name = "Henry VIII";

Jeśli w DSL definicji, właściwość 's rodzaju jest obliczeniowe, nie można go ustawić.Aby uzyskać więcej informacji, zobacz Obliczone i niestandardowe właściwości przechowywania.

Relacje

Relacje domeny, które można zdefiniować w definicji DSL stają się pary właściwości jednej klasy na każdym końcu relacji.Nazwy właściwości są wyświetlane na diagramie DslDefinition jako etykiet na ról na każdej stronie relacji.W zależności od liczebności roli typ właściwości jest klasa na końcu relacji lub kolekcji tej klasy.

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

FamilyTreeModel ftree = henry.FamilyTreeModel;

Właściwości na końcach przeciwnych relacji są zawsze wzajemnych.Kiedy łącze jest tworzone lub usuwane, właściwości roli na oba te elementy są aktualizowane.Następujące wyrażenie (który używa rozszerzeń z System.Linq) jest zawsze prawdziwe dla relacji ParentsHaveChildren w przykładzie:

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

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

ElementLinks.Relacja jest również reprezentowane przez element modelu o nazwie łącze, który jest wystąpieniem typu relacji domeny.Łącze jest zawsze ma jedno źródło elementu oraz jeden obiekt docelowy element.Element źródłowy i docelowy element może być taka sama.

Dostęp można uzyskać łącze i jego właściwości:

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

// This is now true:

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

Domyślnie nie więcej niż jedno wystąpienie relacji może utworzyć łącze między każdą parą elementów modelu.Ale jeśli w definicji DSL, Allow Duplicates flaga jest wartość true dla relacji, a następnie może być więcej niż jedno łącze, i musi być GetLinks:

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

Istnieją również inne metody uzyskiwania dostępu do łączy.Na przykład:

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

Ukryte ról. Jeśli w definicji DSL, Jest generowana przez właściwość jest false dla określonej roli, następnie żadna właściwość nie jest generowana odpowiadające tej roli.Można nadal dostęp do łącza i przechodzenie przez łącza, przy użyciu metod relacji:

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

Przykład najczęściej używane jest PresentationViewsSubject relacja, która łączy element modelu do kształtu, który wyświetla go na diagram:

PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape

Katalog elementu

Można uzyskać dostęp do wszystkich elementów w magazynie, korzystając z katalogu elementu:

store.ElementDirectory.AllElements

Są również metod znajdowania elementów, takich jak:

store.ElementDirectory.FindElements(Person.DomainClassId);

store.ElementDirectory.GetElement(elementId);

Dostęp do informacji, klasa

Można uzyskać informacje dotyczące klas, relacje i inne aspekty definicji DSL.Na przykład:

DomainClassInfo personClass = henry.GetDomainClass();

DomainPropertyInfo birthProperty =

personClass.FindDomainProperty("BirthDate")

DomainRelationshipInfo relationship =

link.GetDomainRelationship();

DomainRoleInfo sourceRole = relationship.DomainRole[0];

Klasy nadrzędne elementy modelu są w następujący sposób:

  • ModelElement — wszystkie elementy i relacje są ModelElements

  • ElementLink - wszystkie relacje są ElementLinks

Wykonać zmiany wewnątrz transakcji

W każdym przypadku, gdy kod program zmienia coś w magazynie, to należy to zrobić wewnątrz transakcji.Dotyczy to wszystkich elementów modelu, relacje, kształty, diagramy i ich właściwości.Aby uzyskać więcej informacji, zobacz Transaction.

Najbardziej wygodną metodę zarządzania transakcji jest z using instrukcji ujęte w try...catch instrukcji:

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.
}

Można utworzyć dowolną liczbę zmian w obrębie jednej transakcji.Można otworzyć nowe transakcje wewnątrz aktywnej transakcji.

Aby wprowadzone zmiany były trwałe, należy Commit transakcji, zanim go jest usuwany.Jeśli wystąpi wyjątek nie wychwycona wewnątrz transakcji magazynu zostaną zresetowane do stanu przed zmianami.

Tworzenie elementów modelu

W tym przykładzie dodaje element do istniejącego modelu:

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!
}

Ten przykład ilustruje te zasadnicze punkty dotyczące tworzenia elementu:

  • Utwórz nowy element w określonej partycji magazynu.Elementy modelu i relacje, ale nie do kształtów jest to zazwyczaj domyślną partycję.

  • Sprawiają, że docelowy osadzania relacji.W DslDefinition w tym przykładzie każda osoba musi być docelowych osadzania relacji FamilyTreeHasPeople.Aby to osiągnąć, możemy można ustawić właściwość FamilyTreeModel rolę obiektu osoba albo dodać osoby do osób właściwości roli obiektu FamilyTreeModel.

  • Ustawianie właściwości nowego elementu, zwłaszcza właściwości, dla którego IsName ma wartość true w DslDefinition.Ta flaga znaczniki właściwość, która służy do identyfikacji elementu jednoznacznie w ramach jego właściciela.W takim przypadku właściwość Name ma tę flagę.

  • Definicja DSL DSL ten musi załadowane do magazynu.Jeśli piszesz rozszerzenie, takich jak polecenie menu, zazwyczaj będzie już prawdą.W pozostałych przypadkach można jawnie załadować modelu do magazynu, lub użyć ModelBus go załadować.Aby uzyskać więcej informacji, zobacz Porady: otwieranie modelu z pliku w kodzie programu.

Po utworzeniu elementu w ten sposób kształt jest tworzona automatycznie (Jeśli modem DSL ma diagram).Wydaje się w lokalizacji przypisywany automatycznie z domyślną kształt, kolor i inne funkcje.Jeśli chcesz kontrolować miejsca i sposobu skojarzonego kształtu, zobacz Tworzenie elementu i jego kształt.

Tworzenie relacji łącza

Istnieją dwie relacje zdefiniowane w przykładzie definicji DSL.Każda relacja definiuje Właściwości roli w klasie na każdym końcu relacji.

Istnieją trzy sposoby, w których można utworzyć wystąpienie relacji.Każdy z tych trzech metod daje taki sam skutek:

  • Ustaw właściwość obiektu pełniącego rolę źródła.Na przykład:

    • familyTree.People.Add(edward);

    • edward.Parents.Add(henry);

  • Ustaw właściwość player roli docelowej.Na przykład:

    • edward.familyTreeModel = familyTree;

      Liczebność ta rola jest 1..1, więc możemy przypisać wartość.

    • henry.Children.Add(edward);

      Liczebność ta rola jest 0..*, więc możemy dodać do kolekcji.

  • Jawnie skonstruować wystąpienia relacji.Na przykład:

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

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

Ostatnia metoda jest użyteczna, jeśli chcesz ustawić właściwości na samą relację.

Po utworzeniu elementu w ten sposób łącznika na diagramie jest tworzona automatycznie, ale ma kształt domyślny, kolor i inne funkcje.Aby kontrolować sposób tworzenia łącznika skojarzone, zobacz Tworzenie elementu i jego kształt.

Usuwanie elementów

Usuwanie elementu, wywołując Delete():

henry.Delete();

Ta operacja spowoduje również usunięcie:

  • Relacja łącza do i z elementu.Na przykład edward.Parents nie będzie zawierał henry.

  • Elementy role, dla którego PropagatesDelete flaga jest wartość true.Na przykład kształt, który wyświetla elementu zostaną usunięte.

Domyślnie, każdy osadzania relacja ma PropagatesDelete true na rolę docelową.Usuwanie henry nie powoduje usunięcia familyTree, ale familyTree.Delete() Usuń wszystkie Persons.Aby uzyskać więcej informacji, zobacz Dostosowywanie zachowania dotyczącego usuwania.

Domyślnie PropagatesDelete nie jest prawdziwe dla ról w relacji odniesienia.

Można spowodować, że zasady usuwania pominąć propagacji określonych podczas usuwania obiektu.Jest to przydatne, jeśli są zastępując jeden element do innego.Należy podać identyfikator GUID jedną lub więcej ról, dla których usunięcie nie powinny być propagowane.Identyfikator GUID, można otrzymać od klasy relacji:

henry.Delete(ParentsHaveChildren.SourceDomainRoleId);

(W tym przykładzie w szczególności będzie miało żadnego efektu, ponieważ PropagatesDelete jest false dla ról z ParentsHaveChildren relacji.)

W niektórych przypadkach usunięcie powiedzie się istnienie lock, element lub element, który będzie usunięty przez propagację.Można użyć element.CanDelete() do sprawdzania, czy można usunąć elementu.

Usuwanie łącza relacji

Łącze relacji można usunąć przez usunięcie elementu z właściwości roli:

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

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

Można także jawnie Usuń łącze:

edwardHenryLink.Delete();

Wszystkie te trzy metody mają ten sam efekt.Trzeba użyć jednej z nich.

Jeśli rola ma liczebność od 0 do 1 lub 1..1, można ją ustawić, null, lub na inną wartość:

edward.FamilyTreeModel = null;/ / lub:

edward.FamilyTreeModel = anotherFamilyTree;

Zmiany kolejności powiązań relacji

Łącza określonego stosunku powierzając jej ich konserwację lub ukierunkowanych na element określonego modelu mają określonej kolejności.Pojawiają się w kolejności, w jakiej zostały dodane.Na przykład ta instrukcja generująca zawsze dzieci w tej samej kolejności:

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

Można zmienić kolejność łączy:

ParentsHaveChildren link = GetLink(henry,edward);

ParentsHaveChildren nextLink = GetLink(henry, elizabeth);

DomainRoleInfo role =

link.GetDomainRelationship().DomainRoles[0];

link.MoveBefore(role, nextLink);

Blokuje

Zmiany może być niemożliwe przez blokadę.Blokady można ustawić dla poszczególnych elementów, partycje i magazynu.Jeśli dowolny z tych poziomów jest zablokowany, uniemożliwiający rodzaj zmian, które chcesz wprowadzić, może być wyjątek przy próbie go.Aby wykryć, czy blokady są ustawione przy użyciu elementu.GetLocks(), która jest metoda rozszerzenia, która jest zdefiniowana w Immutability.

Aby uzyskać więcej informacji, zobacz Definiowanie zasad blokowania na potrzeby tworzenia segmentów tylko do odczytu.

Kopiowanie i wklejanie

Można kopiować elementy lub grup elementów do 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>());

Elementy są przechowywane jako szeregowany grupy elementów.

Elementy z IDataObject można scalić modelu:

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

Merge ()można zaakceptować albo PresentationElement lub ModelElement.Jeśli nadać mu PresentationElement, można również określić pozycji na diagram tarczowy jako trzeci parametr.

Przeglądanie i aktualizowanie diagramów

W DSL elementu modelu domeny, który reprezentuje koncepcji, takich jak osoby lub utworu, jest niezależna od elementu kształtu, który reprezentuje Zobacz na diagramie.Element modelu domeny przechowuje właściwości ważne i relacje pojęcia.Element kształtu są przechowywane, rozmiar, położenie i kolor obiektu widoku na diagramie i jego części składowych układu.

Elementy prezentacji

Diagram klasy podstawowej typów kształt i element

W Państwa definicji DSL każdy element, który można określić tworzy klasę pochodzącej z jednej z następujących klas standardowych.

Rodzaj elementu

Klasa podstawowa

Klasa domeny

ModelElement

Relacja domeny

ElementLink

Kształt

NodeShape

Łącznik

BinaryLinkShape

Diagram

Diagram

Element na diagramie zazwyczaj reprezentuje element modelu.Zazwyczaj (ale nie zawsze) NodeShape reprezentuje wystąpienie klasy do domeny i BinaryLinkShape reprezentuje wystąpienie relacji do domeny.PresentationViewsSubject Relacji łączy kształt węzeł lub łącze do elementu modelu, który reprezentuje.

Każdy kształt węzeł lub łącze należy do jednego diagramu.Kształt łącze binarne łączy dwa kształty węzłów.

Kształty mogą mieć kształtów podrzędnych w dwóch zestawów.Kształt w NestedChildShapes zestawu jest ograniczona do obwiedni jego obiektu nadrzędnego.Kształt w RelativeChildShapes listy mogą być wyświetlane na zewnątrz lub częściowo, poza granicami nadrzędny – na przykład etykietę lub portu.Diagram, nie ma RelativeChildShapes i nie Parent.

Przechodzenie między kształtami i elementy

Elementy modelu domeny i elementy kształtu są powiązane przez PresentationViewsSubject relacji.

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

Takiej samej relacji łączy łączniki na diagramie relacje:

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

Ta relacja także łącza do katalogu głównego modelu do diagramu:

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

Aby uzyskać elementu modelu odpowiadał jednemu kształtowi, należy użyć:

henryShape.ModelElement as Person

diagram.ModelElement as FamilyTreeModel

Nawigacja na diagramie

Ogólnie nie jest wskazane, aby nawigować między kształtami i łącznikami na diagramie.Lepiej nawigować relacje w modelu, przechodzenie między kształtami i łącznikami, tylko w przypadku, gdy jest to niezbędne do pracy na wygląd diagramu jest.Metody te łącze łączniki do kształtów na każdym końcu:

personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes

connector.FromShape, connector.ToShape

Wiele kształtów są kompozyty; składają się z kształtem nadrzędnym i jedną lub więcej warstw podrzędnych.Kształty, które są pozycjonowane względem innego kształtu są określane jako jej dzieci.Gdy zostanie przeniesiony z kształtem nadrzędnym, dzieci są przenoszone wraz z nią.

Względne dzieci mogą być wyświetlane poza obwiednią kształtu nadrzędnego.Zagnieżdżone dzieci ściśle pojawiają się wewnątrz granic obiektu nadrzędnego.

Aby uzyskać zestaw top kształtów na diagramie, należy użyć:

Diagram.NestedChildShapes

Klasy nadrzędne kształty i łączniki są:

ModelElement

-- PresentationElement

-- ShapeElement

----- NodeShape

------- Diagram

------- YourShape

----- LinkShape

------- BinaryLinkShape

--------- YourConnector

Właściwości kształtów i łączników

W większości przypadków nie jest konieczne jawne zmiany kształtów.Gdy zostały zmienione elementy modelu, zasady "Napraw" zaktualizować kształty i łączniki.Aby uzyskać więcej informacji, zobacz Odpowiadanie na zmiany i propagowanie zmian.

Jednakże jest użyteczna do wprowadzania pewnych zmian jawne do kształtów na właściwości, które są niezależne od elementów modelu.Na przykład może zmienić te właściwości:

  • Size-Określa wysokość i szerokość kształtu.

  • Location-położenia względem kształtu nadrzędnego lub diagramu

  • StyleSet-Zestaw piór i pędzle używanych do rysowania łącznik lub kształt

  • Hide-sprawia, że kształt jest niewidoczna

  • Show-powoduje, że kształt jest widoczna poHide()

Tworzenie elementu i jego kształt.

Podczas tworzenia elementu i połączyć go do drzewa osadzania relacje, kształt jest automatycznie tworzone i skojarzony z nim.Polega to na reguły "korekty", które wykonać po zakończeniu transakcji.Kształt pojawi się w lokalizacji automatycznie przypisywany i jego kształt, kolor i inne funkcje będą mieć wartooci domyolnych.Aby kontrolować sposób tworzenia kształtu, można użyć funkcji korespondencji seryjnej.Najpierw Dodaj elementy, które chcesz dodać do ElementGroup, a następnie scalić grupę na diagramie.

Tej metody:

  • Ustawia nazwę, jeśli zostały przypisane właściwości jako nazwa elementu.

  • Przestrzega wszelkich elementu scalania dyrektyw, określonych w definicji DSL.

To przykładowe polecenie tworzy kształt na położenie myszy, gdy użytkownik kliknie dwukrotnie diagramu.W definicji DSL dla tej próbki FillColor właściwość ExampleShape zostały narażone.

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

Jeśli więcej niż jeden kształt, należy ustawić ich pozycji względem siebie za pomocą AbsoluteBounds.

Można również ustawić kolor i inne właściwości narażonych łączników za pomocą tej metody.

Użyj transakcji

Kształty, diagramy i łączniki są podtypami ModelElement i live w magazynie.Dlatego należy zmiany do nich tylko wewnątrz transakcji.Aby uzyskać więcej informacji, zobacz Porady: użycie transakcji do aktualizacji modelu.

Widok dokumentu i danych dokumentu

Diagram klas diagramu standardowych typów

Partycje magazynu

Podczas ładowania modelu diagramu towarzyszących jest ładowany w tym samym czasie.Zazwyczaj modelu jest ładowany do Store.DefaultPartition i zawartość diagramu jest ładowany do innej partycji.Zazwyczaj zawartość każdej partycji jest ładowany i zapisywane w oddzielnym pliku.

Zobacz też

Informacje

ModelElement

Koncepcje

Sprawdzanie poprawności w języku specyficznym dla domeny

Porady: użycie transakcji do aktualizacji modelu

Integrowanie modeli za pomocą Visual Studio Modelbus

Inne zasoby

Generowanie kodu z języka specyficznego dla domeny

Odpowiadanie na zmiany i propagowanie zmian