Aracılığıyla paylaş


Program Kodunda Modelde Gezinme ve Modeli Güncelleştirme

Model öğelerini oluşturmak ve silmek, özelliklerini ayarlamak ve öğeler arasında bağlantılar oluşturup silmek için kod yazabilirsiniz. Tüm değişiklikler bir işlem içinde yapılmalıdır. Öğeler diyagramda görüntüleniyorsa, diyagram işlemin sonunda otomatik olarak "düzeltilir".

Örnek DSL Tanımı

Bu konu başlığı altındaki örnekler için DslDefinition.dsl dosyasının ana bölümü budur:

DSL Definition diagram - family tree model

Bu model, bu DSL'nin bir örneğidir:

Tudor Family Tree Model

Başvurular ve Ad Alanları

Bu konudaki kodu çalıştırmak için aşağıdakilere başvurmanız gerekir:

Microsoft.VisualStudio.Modeling.Sdk.11.0.dll

Kodunuz şu ad alanını kullanır:

using Microsoft.VisualStudio.Modeling;

Ayrıca, kodu DSL'nizin tanımlandığı projeden farklı bir projede yazıyorsanız, DSL projesi tarafından oluşturulan derlemeyi içeri aktarmanız gerekir.

Özellikler

DSL tanımında tanımladığınız etki alanı özellikleri, program kodunda erişebileceğiniz özelliklere dönüşür:

Person henry = ...;

if (henry.BirthDate < 1500) ...

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

Bir özellik ayarlamak istiyorsanız, bunu bir işlem içinde yapmanız gerekir:

henry.Name = "Henry VIII";

DSL tanımında bir özelliğin Kind'i Hesaplanmış ise, bunu ayarlayamazsınız. Daha fazla bilgi için bkz. Hesaplanan ve Özel Depolama Özellikleri.

İlişki

DSL tanımında tanımladığınız etki alanı ilişkileri, ilişkinin her sonundaki sınıfta bir tane olmak üzere özellik çiftleri haline gelir. Özelliklerin adları DslDefinition diyagramında ilişkinin her tarafındaki rollerde etiketler olarak görünür. Rolün çokluğuna bağlı olarak, özelliğin türü ilişkinin diğer ucundaki sınıf veya bu sınıfın koleksiyonudur.

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

FamilyTreeModel ftree = henry.FamilyTreeModel;

İlişkinin karşı uçlarında yer alan özellikler her zaman karşılıklıdır. Bir bağlantı oluşturulduğunda veya silindiğinde, her iki öğedeki rol özellikleri de güncelleştirilir. Aşağıdaki ifade (uzantılarını System.Linqkullanır) örnekteki ParentsHaveChildren ilişkisi için her zaman doğrudur:

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

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

ElementLinks. İlişki, etki alanı ilişki türünün bir örneği olan bağlantı adlı model öğesiyle de temsil edilir. Bağlantının her zaman bir kaynak öğesi ve bir hedef öğesi vardır. Kaynak öğe ve hedef öğe aynı olabilir.

Bağlantıya ve özelliklerine erişebilirsiniz:

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

// This is now true:

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

Varsayılan olarak, bir ilişkinin birden fazla örneğinin herhangi bir model öğesi çiftini bağlamasına izin verilmez. Ancak DSL tanımında Allow Duplicates , ilişki için bayrak doğruysa, birden fazla bağlantı olabilir ve kullanmanız GetLinksgerekir:

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

Bağlantılara erişmek için başka yöntemler de vardır. Örneğin:

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

Gizli roller. DSL tanımında, Belirli bir rol için Oluşturulan Özellik Yanlış ise, o role karşılık gelen hiçbir özellik oluşturulmaz. Ancak, yine de bağlantılara erişebilir ve ilişkinin yöntemlerini kullanarak bağlantılarda geçiş yapabilirsiniz:

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

En sık kullanılan örnek, bir model öğesini diyagramda görüntüleyen şekle bağlayan ilişkidir PresentationViewsSubject :

PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape

Öğe Dizini

öğe dizinini kullanarak depodaki tüm öğelere erişebilirsiniz:

store.ElementDirectory.AllElements

Öğeleri bulmak için aşağıdakiler gibi yöntemler de vardır:

store.ElementDirectory.FindElements(Person.DomainClassId);

store.ElementDirectory.GetElement(elementId);

Sınıf Bilgilerine Erişme

DSL tanımının sınıfları, ilişkileri ve diğer yönleri hakkında bilgi alabilirsiniz. Örneğin:

DomainClassInfo personClass = henry.GetDomainClass();

DomainPropertyInfo birthProperty =

personClass.FindDomainProperty("BirthDate")

DomainRelationshipInfo relationship =

link.GetDomainRelationship();

DomainRoleInfo sourceRole = relationship.DomainRole[0];

Model öğelerinin üst sınıfları aşağıdaki gibidir:

  • ModelElement - tüm öğeler ve ilişkiler ModelElement'lerdir

  • ElementLink - tüm ilişkiler ElementLink'lerdir

İşlem İçinde Değişiklik Yapma

Program kodunuz Mağaza'daki herhangi bir şeyi değiştirdiğinden, bunu bir işlem içinde yapması gerekir. Bu, tüm model öğeleri, ilişkiler, şekiller, diyagramlar ve bunların özellikleri için geçerlidir. Daha fazla bilgi için bkz. Transaction.

bir işlemi yönetmenin en kullanışlı yöntemi, deyiminin içine alınmış bir using try...catch deyimdir:

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

Bir işlem içinde istediğiniz sayıda değişiklik yapabilirsiniz. Etkin bir işlem içinde yeni işlemler açabilirsiniz.

Değişikliklerinizi kalıcı hale getirmek için, atılmadan önce işlemi gerçekleştirmeniz gerekir Commit . İşlemin içinde yakalanmayan bir özel durum oluşursa, Mağaza değişikliklerden önce durumuna sıfırlanır.

Model Öğeleri Oluşturma

Bu örnek, mevcut modele bir öğe ekler:

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

Bu örnekte, öğe oluşturmayla ilgili şu temel noktalar gösterilmektedir:

  • Yeni öğeyi Mağaza'nın belirli bir bölümünde oluşturun. Model öğeleri ve ilişkiler için, ancak şekiller için değil, bu genellikle varsayılan bölümdür.

  • Ekleme ilişkisinin hedefi haline getirin. Bu örneğin DslDefinition'ında, her Kişi FamilyTreeHas Kişiler ilişkisini eklemenin hedefi olmalıdır. Bunu başarmak için, Person nesnesinin FamilyTreeModel rol özelliğini ayarlayabilir veya Person'ı FamilyTreeModel nesnesinin Kişiler rol özelliğine ekleyebiliriz.

  • Yeni bir öğenin özelliklerini, özellikle DslDefinition içinde true olan özelliğini IsName ayarlayın. Bu bayrak, öğesini sahibi içinde benzersiz olarak tanımlamaya hizmet eden özelliği işaretler. Bu durumda Name özelliğinde bu bayrak bulunur.

  • Bu DSL'nin DSL tanımı Mağaza'ya yüklenmiş olmalıdır. Menü komutu gibi bir uzantı yazıyorsanız, bu genellikle zaten doğru olacaktır. Diğer durumlarda, modeli mağazaya açıkça yükleyebilir veya model yüklemek için ModelBus kullanabilirsiniz. Daha fazla bilgi için bkz . Nasıl yapılır: Program Kodunda Dosyadan Model Açma.

    Bu şekilde bir öğe oluşturduğunuzda, otomatik olarak bir şekil oluşturulur (DSL'nin diyagramı varsa). Varsayılan şekil, renk ve diğer özelliklerle otomatik olarak atanan bir konumda görünür. İlişkili şeklin nerede ve nasıl görüneceğini denetlemek istiyorsanız bkz . Öğe oluşturma ve şekli.

Örnek DSL tanımında tanımlanan iki ilişki vardır. Her ilişki, ilişkinin her sonundaki sınıfta bir rol özelliği tanımlar.

bir ilişkinin örneğini oluşturmanın üç yolu vardır. Bu üç yöntemin her biri aynı etkiye sahiptir:

  • Kaynak rol oynatıcının özelliğini ayarlayın. Örneğin:

    • familyTree.People.Add(edward);

    • edward.Parents.Add(henry);

  • Hedef rol oynatıcının özelliğini ayarlayın. Örneğin:

    • edward.familyTreeModel = familyTree;

      Bu rolün çokluğudur 1..1, bu nedenle değeri atarız.

    • henry.Children.Add(edward);

      Bu rolün çokluğu olur 0..*, bu nedenle koleksiyona ekleriz.

  • İlişkinin bir örneğini açıkça oluşturun. Örneğin:

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

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

    Son yöntem, ilişkinin kendisinde özellikleri ayarlamak istiyorsanız kullanışlıdır.

    Bu şekilde bir öğe oluşturduğunuzda, diyagramdaki bir bağlayıcı otomatik olarak oluşturulur, ancak varsayılan bir şekil, renk ve diğer özelliklere sahiptir. İlişkili bağlayıcının nasıl oluşturulduğunu denetlemek için bkz . Öğe ve Şekil Oluşturma.

Öğeleri Silme

öğesini çağırarak Delete()bir öğeyi silin:

henry.Delete();

Bu işlem şunları da siler:

  • öğeye ve öğesinden ilişki bağlantıları. Örneğin, edward.Parents artık içermeyecektir henry.

  • Bayrağın true olduğu rollerdeki PropagatesDelete öğeler. Örneğin, öğesini görüntüleyen şekil silinir.

Varsayılan olarak, hedef rolde her ekleme ilişkisinin true değeri vardır PropagatesDelete . Silme henry işlemi öğesini silmez familyTree, ancak familyTree.Delete() tüm Personsöğesini siler.

Varsayılan olarak, PropagatesDelete başvuru ilişkilerinin rolleri için doğru değildir.

Bir nesneyi sildiğinizde silme kurallarının belirli yaymaları atmasına neden olabilirsiniz. Bu, bir öğeyi başka bir öğe için değiştiriyorsanız kullanışlıdır. Silme işleminin yayılmaması gereken bir veya daha fazla rolün GUID'sini sağlarsınız. GUID, ilişki sınıfından alınabilir:

henry.Delete(ParentsHaveChildren.SourceDomainRoleId);

(İlişkinin rolleri ParentsHaveChildren için olduğundan PropagatesDelete false bu özel örneğin hiçbir etkisi olmaz.)

Bazı durumlarda silme işlemi, öğede veya yayma tarafından silinecek bir öğede bir kilidin bulunmasıyla engellenir. öğesinin silinip silinemeyeceğini denetlemek için kullanabilirsiniz element.CanDelete() .

Bir öğeyi rol özelliğinden kaldırarak ilişki bağlantısını silebilirsiniz:

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

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

Ayrıca bağlantıyı açıkça silebilirsiniz:

edwardHenryLink.Delete();

Bu üç yöntemin tümü aynı etkiye sahiptir. Bunlardan yalnızca birini kullanmanız gerekir.

Rolün 0..1 veya 1..1 çokluğu varsa, bunu nullolarak veya başka bir değere ayarlayabilirsiniz:

edward.FamilyTreeModel = null; Veya:

edward.FamilyTreeModel = anotherFamilyTree;

bir İlişkinin Bağlantılarını Yeniden Sıralama

Belirli bir model öğesinde kaynaklanan veya hedeflenen belirli bir ilişkinin bağlantıları belirli bir diziye sahiptir. Eklendikleri sırada görünürler. Örneğin, bu deyim her zaman alt öğeleri aynı sırada verir:

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

Bağlantıların sırasını değiştirebilirsiniz:

ParentsHaveChildren link = GetLink(henry,edward);

ParentsHaveChildren nextLink = GetLink(henry, elizabeth);

DomainRoleInfo role =

link.GetDomainRelationship().DomainRoles[0];

link.MoveBefore(role, nextLink);

Kilitler

Değişiklikleriniz bir kilit tarafından engellenebilir. Kilitler tek tek öğelerde, bölümlerde ve depoda ayarlanabilir. Bu düzeylerden herhangi birinin yapmak istediğiniz değişiklik türünü engelleyen bir kilidi varsa, bunu denediğinizde bir özel durum oluşturulabilir. Kilitlerin öğesini kullanarak ayarlanıp ayarlanmadığını keşfedebilirsiniz. GetLocks(), ad alanında Microsoft.VisualStudio.Modeling.Immutabilitytanımlanan bir uzantı yöntemidir.

Daha fazla bilgi için bkz . Salt Okunur Segmentler Oluşturmak için Kilitleme İlkesi Tanımlama.

Kopyala ve Yapıştır

Öğeleri veya öğe gruplarını öğesine IDataObjectkopyalayabilirsiniz:

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

Öğeler serileştirilmiş Öğe Grubu olarak depolanır.

Bir IDataObject öğesindeki öğeleri bir modelle birleştirebilirsiniz:

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

Merge ()veya ModelElementkabul PresentationElement edebilir. Bir verirseniz PresentationElement, hedef diyagramda üçüncü parametre olarak bir konum da belirtebilirsiniz.

Diyagramlarda gezinme ve diyagramları güncelleştirme

DSL'de, Person veya Song gibi bir kavramı temsil eden etki alanı modeli öğesi, diyagramda gördüklerinizi temsil eden şekil öğesinden ayrıdır. Etki alanı modeli öğesi, kavramların önemli özelliklerini ve ilişkilerini depolar. Şekil öğesi diyagramda nesne görünümünün boyutunu, konumunu ve rengini ve bileşen parçalarının düzenini depolar.

Sunu Öğeleri

Class diagram of base shape and element types

DSL Tanımınızda, belirttiğiniz her öğe aşağıdaki standart sınıflardan birinden türetilen bir sınıf oluşturur.

Öğe türü Temel sınıf
Etki alanı sınıfı ModelElement
Etki alanı ilişkisi ElementLink
Şekil NodeShape
Bağlayıcı BinaryLinkShape
Diyagram Diagram

Diyagramdaki bir öğe genellikle bir model öğesini temsil eder. Genellikle (ancak her zaman değil), bir NodeShape etki alanı sınıfı örneğini ve bir BinaryLinkShape etki alanı ilişki örneğini temsil eder. İlişki, PresentationViewsSubject bir düğümü veya şekli temsil ettiği model öğesine bağlar.

Her düğüm veya bağlantı şekli bir diyagrama aittir. İkili bağlantı şekli iki düğüm şeklini bağlar.

Şekiller iki kümede alt şekillere sahip olabilir. Kümedeki NestedChildShapes bir şekil, üst öğesinin sınırlayıcı kutusuyla sınırlandırılır. Listedeki bir şekil RelativeChildShapes üst öğe sınırlarının dışında veya kısmen dışında (örneğin, bir etiket veya bağlantı noktası) görüntülenebilir. Diyagramda yok RelativeChildShapes ve yok Parentvar.

Şekiller ve öğeler arasında gezinme

Etki alanı modeli öğeleri ve şekil öğeleri ilişkiyle PresentationViewsSubject ilişkilidir.

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

Aynı ilişki, ilişkileri diyagramdaki bağlayıcılara bağlar:

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

Bu ilişki ayrıca modelin kökünü diyagrama bağlar:

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

Bir şekille temsil edilen model öğesini almak için şunu kullanın:

henryShape.ModelElement as Person

diagram.ModelElement as FamilyTreeModel

Genel olarak diyagramdaki şekiller ve bağlayıcılar arasında gezinmek önerilmez. Modeldeki ilişkilerde gezinmek, şekiller ve bağlayıcılar arasında yalnızca diyagramın görünümü üzerinde çalışmak gerektiğinde gezinmek daha iyidir. Bu yöntemler bağlayıcıları her uçta şekillere bağlar:

personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes

connector.FromShape, connector.ToShape

Birçok şekil bileşiktir; bir üst şekil ve bir veya daha fazla alt katmandan oluşur. Başka bir şekle göre konumlandırılan şekillerin alt öğeleri olduğu söylenir. Üst şekil hareket ettiğinde, alt öğeler de onunla birlikte hareket eder.

Göreli alt öğeler üst şeklin sınırlayıcı kutusunun dışında görünebilir. İç içe alt öğeler kesinlikle üst öğe sınırlarının içinde görünür.

Diyagramdaki en üst şekil kümesini elde etmek için şunu kullanın:

Diagram.NestedChildShapes

Şekillerin ve bağlayıcıların ata sınıfları şunlardır:

ModelElement

-- PresentationElement

-- ShapeElement

----- NodeShape

------- Diagram

------- Şekliniz

----- LinkShape

------- BinaryLinkShape

--------- Bağlan

Şekillerin ve Bağlan örlerin Özellikleri

Çoğu durumda, şekillerde açık değişiklikler yapmak gerekli değildir. Model öğelerini değiştirdiğinizde, "düzeltme" kuralları şekilleri ve bağlayıcıları güncelleştirir. Daha fazla bilgi için bkz . Değişiklikleri Yanıtlama ve Yayma.

Ancak, model öğelerinden bağımsız özelliklerdeki şekillerde bazı açık değişiklikler yapmak yararlıdır. Örneğin, şu özellikleri değiştirebilirsiniz:

  • Size - şeklin yüksekliğini ve genişliğini belirler.

  • Location - üst şekle veya diyagrama göre konum

  • StyleSet - şekli veya bağlayıcıyı çizmek için kullanılan kalem ve fırça kümesi

  • Hide - şekli görünmez yapar

  • Show - şekli bir Hide()

Öğe ve Şekli Oluşturma

Bir öğe oluşturduğunuzda ve bu öğeyi ilişkileri ekleme ağacına bağladığınızda, şekil otomatik olarak oluşturulur ve onunla ilişkilendirilir. Bu işlem, işlemin sonunda yürütülen "düzeltme" kuralları tarafından gerçekleştirilir. Ancak, şekil otomatik olarak atanan bir konumda görünür ve şekli, rengi ve diğer özellikleri varsayılan değerlere sahip olur. Şeklin nasıl oluşturulduğunu denetlemek için birleştirme işlevini kullanabilirsiniz. Önce bir ElementGroup'a eklemek istediğiniz öğeleri eklemeniz ve ardından grubu diyagramda birleştirmeniz gerekir.

Bu yöntem:

  • Öğe adı olarak bir özellik atadıysanız adı ayarlar.

  • DSL Tanımında belirttiğiniz tüm Öğe Birleştirme Yönergelerini gözlemler.

Bu örnek, kullanıcı diyagrama çift tıkladığında fare konumunda bir şekil oluşturur. Bu örneğin DSL Tanımında FillColor özelliği ExampleShape kullanıma sunuldu.

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

Birden fazla şekil sağlarsanız, kullanarak AbsoluteBoundsgöreli konumlarını ayarlayın.

Bu yöntemi kullanarak bağlayıcıların rengini ve diğer kullanıma sunulan özelliklerini de ayarlayabilirsiniz.

İşlemleri Kullanma

Şekiller, bağlayıcılar ve diyagramlar, Mağaza'nın ModelElement alt türleridir ve Mağaza'da bulunur. Bu nedenle, bu işlemlerde yalnızca bir işlem içinde değişiklik yapmanız gerekir. Daha fazla bilgi için bkz . Nasıl yapılır: Modeli Güncelleştirmek için İşlemleri Kullanma.

Belge Görünümü ve Belge Verileri

Class diagram of standard diagram types

Bölümleri Depolama

Bir model yüklendiğinde, eşlik eden diyagram aynı anda yüklenir. Genellikle model Store.DefaultPartition'a yüklenir ve diyagram içeriği başka bir Bölüme yüklenir. Genellikle her bölümün içeriği yüklenir ve ayrı bir dosyaya kaydedilir.