Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Anda dapat menulis kode untuk membuat dan menghapus elemen model, mengatur propertinya, dan membuat dan menghapus tautan antar elemen. Semua perubahan harus dilakukan dalam transaksi. Jika elemen ditampilkan pada diagram, diagram akan "diperbaiki" secara otomatis di akhir transaksi.
Contoh definisi DSL
Ini adalah bagian utama dari DslDefinition.dsl untuk contoh dalam topik ini:
Model ini adalah instance dari DSL ini:
Referensi dan Namespace
Untuk menjalankan kode dalam topik ini, Anda harus mereferensikan:
Microsoft.VisualStudio.Modeling.Sdk.11.0.dll
Kode Anda akan menggunakan namespace ini:
using Microsoft.VisualStudio.Modeling;
Selain itu, jika Anda menulis kode dalam proyek yang berbeda dari yang didefinisikan DSL Anda, Anda harus mengimpor rakitan yang dibangun oleh proyek Dsl.
Menavigasi Model
Karakteristik
Properti domain yang Anda tentukan dalam definisi DSL menjadi properti yang dapat Anda akses dalam kode program:
Person henry = ...;
if (henry.BirthDate < 1500) ...
if (henry.Name.EndsWith("VIII")) ...
Jika Anda ingin mengatur properti, Anda harus melakukannya di dalam transaksi:
henry.Name = "Henry VIII";
Jika dalam definisi DSL, Jenis sebuah properti adalah Dihitung, Anda tidak dapat mengubahnya. Untuk informasi selengkapnya, lihat Properti Penyimpanan Terhitung dan Kustom.
Hubungan
Hubungan domain yang Anda tentukan dalam definisi DSL menjadi pasangan properti, satu pada kelas di masing-masing ujung hubungan. Nama properti muncul dalam diagram DslDefinition sebagai label pada peran di setiap sisi hubungan. Tergantung pada jumlah peran, tipe properti adalah kelas di ujung lain dari hubungan, atau koleksi kelas tersebut.
foreach (Person child in henry.Children) { ... }
FamilyTreeModel ftree = henry.FamilyTreeModel;
Sifat-sifat di kedua ujung yang berlawanan dari suatu hubungan selalu timbal balik. Saat tautan dibuat atau dihapus, properti peran pada kedua elemen diperbarui. Ekspresi berikut (yang menggunakan ekstensi System.Linq) selalu berlaku untuk hubungan ParentsHaveChildren dalam contoh:
(Person p) => p.Children.All(child => child.Parents.Contains(p))
&& p.Parents.All(parent => parent.Children.Contains(p));
ElementLinks. Hubungan juga diwakili oleh elemen model yang disebut tautan, yang merupakan instans jenis hubungan domain. Tautan selalu memiliki satu elemen sumber dan satu elemen target. Elemen sumber dan elemen target bisa sama.
Anda dapat mengakses tautan dan propertinya:
ParentsHaveChildren link = ParentsHaveChildren.GetLink(henry, edward);
// This is now true:
link == null || link.Parent == henry && link.Child == edward
Secara default, tidak lebih dari satu instans hubungan diizinkan untuk menautkan sepasang elemen model apa pun. Tetapi jika dalam definisi DSL, Allow Duplicates flag benar untuk hubungan tersebut, maka mungkin ada lebih dari satu tautan yang tersedia, dan kamu harus menggunakan GetLinks:
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinks(henry, edward)) { ... }
Ada juga metode lain untuk mengakses tautan. Contohnya:
foreach (ParentsHaveChildren link in ParentsHaveChildren.GetLinksToChildren(henry)) { ... }
Peran tersembunyi. Jika dalam definisi DSL, Apakah Properti Dihasilkan adalah false untuk peran tertentu, maka tidak ada properti yang dihasilkan yang sesuai dengan peran tersebut. Namun, Anda masih dapat mengakses tautan dan melintasi tautan menggunakan metode hubungan:
foreach (Person p in ParentsHaveChildren.GetChildren(henry)) { ... }
Contoh yang paling sering digunakan adalah PresentationViewsSubject hubungan, yang menautkan elemen model ke bentuk yang menampilkannya pada diagram:
PresentationViewsSubject.GetPresentation(henry)[0] as PersonShape
Direktori Elemen
Anda dapat mengakses semua elemen di penyimpanan menggunakan direktori elemen:
store.ElementDirectory.AllElements
Ada juga metode untuk menemukan elemen, seperti berikut ini:
store.ElementDirectory.FindElements(Person.DomainClassId);
store.ElementDirectory.GetElement(elementId);
Mengakses Informasi Kelas
Anda bisa mendapatkan informasi tentang kelas, hubungan, dan aspek lain dari definisi DSL. Contohnya:
DomainClassInfo personClass = henry.GetDomainClass();
DomainPropertyInfo birthProperty =
personClass.FindDomainProperty("BirthDate")
DomainRelationshipInfo relationship =
link.GetDomainRelationship();
DomainRoleInfo sourceRole = relationship.DomainRole[0];
Kelas leluhur elemen model adalah sebagai berikut:
ModelElement - semua elemen dan hubungan adalah ModelElements
ElementLink - semua relasi adalah ElementLinks
Melakukan Perubahan di dalam Transaksi
Setiap kali kode program Anda mengubah apa pun di Toko, kode tersebut harus melakukannya di dalam transaksi. Ini berlaku untuk semua elemen model, hubungan, bentuk, diagram, dan propertinya. Untuk informasi selengkapnya, lihat Transaction .
Metode paling nyaman untuk mengelola transaksi adalah dengan using pernyataan yang diapit dalam pernyataan 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.
}
Anda dapat membuat sejumlah perubahan di dalam satu transaksi. Anda dapat membuka transaksi baru di dalam transaksi aktif.
Untuk membuat perubahan permanen, Anda harus Commit melakukan transaksi sebelum dibuang. Jika terjadi pengecualian yang tidak tertangkap di dalam transaksi, Store akan diatur ulang ke keadaan sebelum perubahan dilakukan.
Membuat Elemen Model
Contoh ini menambahkan elemen ke model yang sudah ada:
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!
}
Contoh ini mengilustrasikan poin-poin penting ini tentang membuat elemen:
Buat elemen baru dalam partisi tertentu dari Store. Untuk elemen dan hubungan model, tetapi bukan bentuk, biasanya ini adalah partisi default.
Jadikan sebagai target dalam hubungan penyematan. Dalam DslDefinition dari contoh ini, setiap Orang harus menjadi target dari hubungan penyematan FamilyTreeHasPeople. Untuk mencapai hal ini, kita dapat mengatur properti peran FamilyTreeModel dari objek Person, atau menambahkan objek Person ke properti peran People dari objek FamilyTreeModel.
Atur properti elemen baru, terutama properti yang
IsNamebenar di DslDefinition. Bendera ini menandai properti yang berfungsi untuk mengidentifikasi elemen secara unik dalam pemiliknya. Dalam hal ini, properti Nama memiliki bendera tersebut.Definisi DSL dari DSL ini harus telah dimuat ke dalam Store. Jika Anda menulis ekstensi seperti perintah menu, ini biasanya sudah benar. Dalam kasus lain, Anda dapat secara eksplisit memuat model ke penyimpanan, atau menggunakan ModelBus untuk memuatnya. Untuk informasi selengkapnya, lihat Cara: Membuka Model dari File dalam Kode Program.
Saat Anda membuat elemen dengan cara ini, bentuk secara otomatis dibuat (jika DSL memiliki diagram). Ini muncul di lokasi yang ditetapkan secara otomatis, dengan bentuk, warna, dan fitur default lainnya. Jika Anda ingin mengontrol di mana dan bagaimana bentuk terkait muncul, lihat Membuat Elemen dan Bentuknya.
Membuat Tautan Hubungan
Ada dua hubungan yang ditentukan dalam contoh definisi DSL. Setiap hubungan mendefinisikan properti peran pada kelas di setiap akhir hubungan.
Ada tiga cara di mana Anda dapat membuat instans hubungan. Masing-masing dari ketiga metode ini memiliki efek yang sama:
Konfigurasi properti dari peran sumber. Contohnya:
familyTree.People.Add(edward);edward.Parents.Add(henry);
Atur properti dari peran sasaran. Contohnya:
edward.familyTreeModel = familyTree;Kelipatan peran ini adalah
1..1, jadi kami menetapkan nilainya.henry.Children.Add(edward);Kemajemukan peran ini adalah
0..*, jadi kami menambahkannya ke kumpulan.
Buat instance hubungan secara eksplisit. Contohnya:
FamilyTreeHasPeople edwardLink = new FamilyTreeHasPeople(familyTreeModel, edward);ParentsHaveChildren edwardHenryLink = new ParentsHaveChildren(henry, edward);
Metode terakhir berguna jika Anda ingin mengatur properti pada hubungan itu sendiri.
Saat Anda membuat elemen dengan cara ini, konektor pada diagram dibuat secara otomatis, tetapi memiliki bentuk, warna, dan fitur default lainnya. Untuk mengontrol bagaimana konektor terkait dibuat, lihat Membuat Elemen dan Bentuknya.
Menghapus Elemen
Hapus elemen dengan memanggil Delete():
henry.Delete();
Operasi ini juga akan menghapus:
Hubungan tautan dari dan ke elemen tersebut. Misalnya,
edward.Parentstidak akan lagi berisihenry.Elemen untuk peran di mana flag
PropagatesDeletediaktifkan. Misalnya, bentuk yang menampilkan elemen akan dihapus.
Secara default, setiap hubungan penyematan memiliki PropagatesDelete true pada peran target. Menghapus henry tidak menghapus familyTree, tetapi familyTree.Delete() akan menghapus semua Persons.
Secara default, PropagatesDelete tidak berlaku untuk peran hubungan referensi.
Anda dapat menyebabkan aturan penghapusan menghilangkan penyebaran tertentu saat Anda menghapus objek. Ini berguna jika Anda mengganti satu elemen untuk elemen lain. Anda menyediakan GUID dari satu atau beberapa peran yang penghapusannya tidak boleh disebarluaskan. GUID dapat diperoleh dari kelas relasi:
henry.Delete(ParentsHaveChildren.SourceDomainRoleId);
(Contoh khusus ini tidak akan berpengaruh, karena PropagatesDelete adalah false untuk peran dalam hubungan ParentsHaveChildren.)
Dalam beberapa kasus, penghapusan dicegah oleh keberadaan kunci, baik pada elemen atau pada elemen yang akan dihapus oleh penyebaran. Anda dapat menggunakan element.CanDelete() untuk memeriksa apakah elemen dapat dihapus.
Menghapus Tautan Hubungan
Anda dapat menghapus tautan hubungan dengan menghapus elemen dari properti peran:
henry.Children.Remove(edward); // or:
edward.Parents.Remove(henry); // or:
Anda juga dapat menghapus tautan secara eksplisit:
edwardHenryLink.Delete();
Ketiga metode ini semuanya memiliki efek yang sama. Anda hanya perlu menggunakan salah satunya.
Jika peran memiliki kelipatan 0..1 atau 1..1, Anda dapat mengaturnya ke null, atau ke nilai lain:
edward.FamilyTreeModel = null; atau:
edward.FamilyTreeModel = anotherFamilyTree;
Mengurutkan ulang Tautan Hubungan
Tautan hubungan tertentu yang bersumber atau ditargetkan pada elemen model tertentu memiliki urutan tertentu. Mereka muncul dalam urutan penambahannya. Misalnya, pernyataan ini akan selalu menghasilkan anak-anak dalam urutan yang sama:
foreach (Person child in henry.Children) ...
Anda dapat mengubah urutan tautan:
ParentsHaveChildren link = GetLink(henry,edward);
ParentsHaveChildren nextLink = GetLink(henry, elizabeth);
DomainRoleInfo role =
link.GetDomainRelationship().DomainRoles[0];
link.MoveBefore(role, nextLink);
Locks
Perubahan Anda mungkin dicegah dengan kunci. Kunci dapat diatur pada elemen individual, pada partisi, dan di toko. Jika salah satu level ini memiliki kunci yang mencegah jenis perubahan yang ingin Anda buat, pengecualian mungkin dilemparkan saat Anda mencobanya. Anda dapat menemukan apakah kunci diatur dengan menggunakan elemen. GetLocks(), yang merupakan metode ekstensi yang ditentukan dalam namespace Microsoft.VisualStudio.Modeling.Immutability.
Untuk informasi selengkapnya, lihat Menentukan Kebijakan Penguncian untuk Membuat Segmen Read-Only.
Salin dan Tempel
Anda dapat menyalin elemen atau grup elemen ke 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>());
Elemen disimpan sebagai Grup Elemen berseri.
Anda dapat menggabungkan elemen dari IDataObject ke dalam model:
using (Transaction t = targetDiagram.Store.
TransactionManager.BeginTransaction("paste"))
{
adopterShape.Diagram.ElementOperations.Merge(adopter, data);
}
Merge () dapat menerima baik PresentationElement maupun ModelElement. Jika Anda memberinya PresentationElement, Anda juga dapat menentukan posisi pada diagram target sebagai parameter ketiga.
Menavigasi dan memperbarui diagram
Dalam DSL, elemen model domain, yang mewakili konsep seperti Orang atau Lagu, terpisah dari elemen bentuk, yang mewakili apa yang Anda lihat pada diagram. Elemen model domain menyimpan properti dan hubungan penting dari konsep. Elemen bentuk menyimpan ukuran, posisi, dan warna tampilan objek pada diagram, dan tata letak bagian komponennya.
Komponen Presentasi
Dalam Definisi DSL Anda, setiap elemen yang Anda tentukan membuat kelas yang berasal dari salah satu kelas standar berikut.
| Jenis elemen | Kelas dasar |
|---|---|
| Kelas domain | ModelElement |
| Hubungan domain | ElementLink |
| Shape | NodeShape |
| Connector | BinaryLinkShape |
| Diagram | Diagram |
Elemen pada diagram biasanya mewakili elemen model. Biasanya (tetapi tidak selalu), NodeShape mewakili sebuah instans kelas domain, dan BinaryLinkShape mewakili sebuah instans hubungan domain. Hubungan ini PresentationViewsSubject menautkan simpul atau bentuk tautan ke elemen model yang diwakilinya.
Setiap simpul atau bentuk tautan milik satu diagram. Bentuk tautan biner menyambungkan dua bentuk simpul.
Bentuk bisa memiliki bentuk anak dalam dua set. Bentuk dalam NestedChildShapes set terbatas pada kotak pembatas induknya. Sebuah bentuk dalam daftar RelativeChildShapes dapat muncul di luar atau sebagian di luar batas elemen induk - misalnya label atau port. Diagram tidak memiliki RelativeChildShapes dan tidak ada Parent.
Menavigasi antara bentuk dan elemen
Elemen model domain dan elemen bentuk terkait dengan PresentationViewsSubject hubungan.
// using Microsoft.VisualStudio.Modeling;
// using Microsoft.VisualStudio.Modeling.Diagrams;
// using System.Linq;
Person henry = ...;
PersonShape henryShape =
PresentationViewsSubject.GetPresentation(henry)
.FirstOrDefault() as PersonShape;
Hubungan yang sama menghubungkan hubungan dengan konektor pada diagram.
Descendants link = Descendants.GetLink(henry, edward);
DescendantConnector dc =
PresentationViewsSubject.GetPresentation(link)
.FirstOrDefault() as DescendantConnector;
// dc.FromShape == henryShape && dc.ToShape == edwardShape
Hubungan ini juga menautkan akar model ke diagram:
FamilyTreeDiagram diagram =
PresentationViewsSubject.GetPresentation(familyTree)
.FirstOrDefault() as FamilyTreeDiagram;
Untuk mendapatkan elemen model yang diwakili oleh bentuk, gunakan:
henryShape.ModelElement as Person
diagram.ModelElement as FamilyTreeModel
Menavigasi di sekitar Diagram
Secara umum tidak disarankan untuk menavigasi antara bentuk dan konektor pada diagram. Lebih baik menavigasi hubungan dalam model, bergerak antara bentuk dan konektor hanya ketika perlu untuk bekerja pada tampilan diagram. Metode ini menautkan konektor ke bentuk di setiap ujung:
personShape.FromRoleLinkShapes, personShape.ToRoleLinkShapes
connector.FromShape, connector.ToShape
Banyak bentuk adalah komposit; mereka terdiri dari bentuk induk dan satu atau beberapa lapisan anak. Bentuk yang diposisikan relatif terhadap bentuk lain dikatakan sebagai anak-anaknya. Ketika bentuk induk bergerak, anak-anak bergerak bersamanya.
Anak-anak relatif dapat muncul di luar kotak pembatas bentuk induk. Anak tertanam muncul secara ketat di dalam batas induk.
Untuk mendapatkan set bentuk atas pada diagram, gunakan:
Diagram.NestedChildShapes
Kelas induk dari bentuk dan konektor adalah:
-- ShapeElement
----- NodeShape
------- Diagram
------- YourShape
----- LinkShape
------- BinaryLinkShape
--------- YourConnector
Properti Bentuk dan Konektor
Dalam kebanyakan kasus, tidak perlu membuat perubahan eksplisit pada bentuk. Ketika Anda telah mengubah elemen model, aturan "pengaturan ulang" memperbarui bentuk dan konektor. Untuk informasi selengkapnya, lihat Merespons dan Menyebarkan Perubahan.
Namun, berguna untuk membuat beberapa perubahan eksplisit pada bentuk dalam properti yang independen dari elemen model. Misalnya, Anda dapat mengubah properti ini:
Size - menentukan tinggi dan lebar bentuk.
Location - posisi relatif terhadap bentuk atau diagram induk
StyleSet - set pena dan kuas yang digunakan untuk menggambar bentuk atau konektor
Hide - membuat bentuk tidak terlihat
Show - membuat bentuk terlihat setelah
Hide()
Membuat Elemen dan Bentuknya
Saat Anda membuat elemen dan memasukkannya ke dalam hierarki hubungan, bentuk secara otomatis dibuat dan dikaitkan dengannya. Ini dilakukan oleh aturan "penyempurnaan" yang dijalankan di akhir transaksi. Namun, bentuk akan muncul di lokasi yang ditetapkan secara otomatis, dan bentuknya, warna dan fitur lainnya akan memiliki nilai default. Untuk mengontrol bagaimana bentuk dibuat, Anda dapat menggunakan fungsi penggabungan. Anda harus terlebih dahulu menambahkan elemen yang ingin Anda tambahkan ke dalam ElementGroup, lalu menggabungkan grup ke dalam diagram.
Metode ini:
Mengatur nama, jika Anda telah menetapkan properti sebagai nama elemen.
Memperhatikan setiap Direktif Penggabungan Elemen yang Anda tentukan dalam Definisi DSL.
Contoh ini membuat bentuk pada posisi mouse, ketika pengguna mengklik dua kali diagram. Dalam Definisi DSL untuk sampel ini, properti FillColor dari ExampleShape telah dipaparkan.
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();
}
}
}
Jika Anda menyediakan lebih dari satu bentuk, atur posisi relatifnya menggunakan AbsoluteBounds.
Anda juga dapat mengatur warna dan properti konektor lain yang terekspos menggunakan metode ini.
Gunakan Transaksi
Bentuk, konektor, dan diagram adalah subjenis ModelElement dan berada di Toko. Oleh karena itu, Anda hanya dapat membuat perubahan pada mereka di dalam sebuah transaksi. Untuk informasi selengkapnya, lihat Cara: Menggunakan Transaksi untuk Memperbarui Model.
Tampilan Dokumen dan Data Dokumen
Partisi Penyimpanan
Saat model dimuat, diagram yang menyertainya dimuat secara bersamaan. Biasanya, model dimuat ke Store.DefaultPartition, dan konten diagram dimuat ke partisi lain. Biasanya, konten setiap partisi dimuat dan disimpan ke file terpisah.