建立 Windows Forms 架構的特定領域語言
您可以使用 Windows Forms 來顯示特定領域語言 (DSL) 模型的狀態,而不是使用 DSL 圖表。 本主題會逐步引導您使用 Visual Studio Visualization and Modeling SDK 將 Windows Form 繫結至 DSL。
下圖顯示 DSL 執行個體的 Windows Form UI 和模型總管:
建立 Windows Forms DSL
最小 WinForm 設計工具 DSL 範本會建立最小 DSL,您可以修改以符合自己的需求。
從最小 WinForm 設計工具範本建立 DSL。
在本逐步解說中,假設有下列名稱:
- 解決方案和 DSL 名稱:
FarmApp
- 命名空間:
Company.FarmApp
- 解決方案和 DSL 名稱:
實驗範本提供的初始範例:
轉換所有範本。
建置並執行範例 (Ctrl+F5)。
在 Visual Studio 的實驗執行個體中,開啟偵錯專案中的
Sample
檔案。請注意,該檔案會顯示在 Windows Forms 控制項中。
您也可以查看 [總管] 中顯示的模型元素。
在表單或檔案總管中新增一些元素,並注意其出現在另一個顯示中。
在 Visual Studio 的主要執行個體中,請注意有關 DSL 解決方案的下列幾點:
DslDefinition.dsl
不包含任何圖表元素。 這是因為您不會使用 DSL 圖表來檢視此 DSL 的執行個體模型。 相反地,您會將 Windows Form 繫結至模型,而表單上的元素會顯示模型。除了
Dsl
和DslPackage
專案之外,解決方案還包含名為UI.
UI 專案的第三個專案,其中包含 Windows Forms 控制項的定義。DslPackage
相依於UI
,而UI
相依於Dsl
。在
DslPackage
專案中,UI\DocView.cs
包含程式碼,顯示UI
專案中定義的 Windows Forms 控制項。UI
專案包含繫結至 DSL 之表單控制項的工作範例。 不過,當您變更 DSL 定義時,將無法運作。UI
專案包含:名為
ModelViewControl
的 Windows Form 類別。名為
DataBinding.cs
的檔案,其中包含ModelViewControl
的額外部分定義。 若要查看其內容,請在 [方案總管] 中,開啟檔案的捷徑功能表,然後選擇 [檢視程式碼]。
關於 UI 專案
當您更新 DSL 定義檔來定義自己的 DSL 時,您必須更新 UI
專案中的控制項以顯示您的 DSL。 不同於 Dsl
和 DslPackage
專案,範例 UI
專案不會從 DslDefinitionl.dsl
產生。 如果您想要的話,您可以新增 .tt 檔案來產生程式碼,但是本逐步解說中並未涵蓋。
更新 DSL 定義
下圖是本逐步解說中使用的 DSL 定義。
在 DSL 設計工具中開啟 DslDefinition.dsl。
刪除 [ExampleElement]
將 ExampleModel 領域類別重新命名為
Farm
。為其提供類型為 Int32 時名為
Size
、類型為布林值時名為IsOrganic
的額外領域屬性。注意
如果您刪除根領域類別,然後建立新的根領域類別,則必須重設編輯器根類別屬性。 在 DSL 總管中,選取 [編輯器]。 然後在 [屬性] 視窗中,將 [根類別] 設定為
Farm
。使用具名領域類別工具來建立下列領域類別:
Field
- 為此項目提供名為Size
的額外領域屬性。Animal
- 在 [屬性] 視窗中,將 [繼承修飾元] 設定為 [抽象]。
注意
具名領域類別工具和本節中所述的其他工具可以在 [工具箱] 工具視窗中找到。 您可以使用 [檢視] > [工具箱] 來開啟或隱藏此視窗。
使用領域類別工具來建立下列類別:
Sheep
Goat
使用繼承工具讓
Goat
和Sheep
從Animal
繼承。使用內嵌工具在
Farm
底下內嵌Field
和Animal
。您可能想要清理圖表。 若要減少重複元素的數目,請使用分葉元素捷徑功能表上的 [將樹狀子目錄放到這裡] 命令。
[方案總管] 的工具列中的 [轉換所有範本]。
建置 Dsl 專案。
注意
在這個階段,其他專案將不會建置,不會發生錯誤。 不過,我們想要建置 Dsl 專案,使其組件可供資料來源精靈使用。
更新 UI 專案
現在您可以建立新的使用者控制項,以顯示儲存在 DSL 模型中的資訊。 將使用者控制項連線到模型最簡單的方式是透過資料繫結。 名為 ModelingBindingSource 的資料繫結配接器類型特別設計為將 DSL 連線到非 VMSDK 介面。
將您的 DSL 模型定義為資料來源
選擇 [資料] 功能表上的 [顯示資料來源]。
[資料來源] 視窗隨即開啟。
選擇 [加入新資料來源]。 [資料來源組態精靈] 隨即開啟。
選擇 [物件]、[下一步]。
展開 [Dsl]、[Company.FarmApp],然後選取 [Farm],這是您模型的根類別。 選擇 [完成]。
在 [方案總管] 中,UI 專案現在包含 Properties\DataSources\Farm.datasource
模型類別的屬性和關聯性會出現在 [資料來源] 視窗中。
將模型連線到表單
在 UI 專案中,刪除所有現有的 .cs 檔案。
將名為
FarmControl
的新使用者控制項檔案新增至 UI 專案。在 [資料來源] 視窗的 [伺服器陣列] 下拉式功能表上,選擇 [詳細資料]。
針對其他屬性保留預設設定。
在設計檢視中開啟 FarmControl.cs。
將 [伺服器陣列] 從 [資料來源] 視窗拖曳至 FarmControl。
一組控制項隨即出現,每個屬性各一個控制項。 關聯性屬性不會產生控制項。
刪除 farmBindingNavigator。 這也會在
FarmControl
設計工具中自動產生,但是不適用於此應用程式。使用工具箱,建立兩個 DataGridView 的執行個體,並將其命名為
AnimalGridView
和FieldGridView
。注意
替代的步驟是將「動物」和「欄位」項目從 [資料來源] 視窗拖曳至控制項。 此動作會自動在方格檢視與資料來源之間建立資料格線和繫結。 不過,此繫結不適用於 DSL。 因此,最好手動建立資料格線和繫結。
如果 [工具箱] 不包含 ModelingBindingSource 工具,請加以新增。 在 [資料] 索引標籤的捷徑功能表上,選擇 [選擇項目]。 在 [選擇工具箱項目] 對話方塊中,從 [.NET Framework] 索引標籤中選取 [ModelingBindingSource]。
使用工具箱,建立兩個 ModelingBindingSource 的執行個體,並將其命名為
AnimalBinding
和FieldBinding
。將每個 ModelingBindingSource 的 DataSource 屬性設定為 farmBindingSource。
將 DataMember 屬性設定為 Animals 或 Fields。
將
AnimalGridView
的 DataSource 屬性設定為AnimalBinding
,以及將FieldGridView
的該屬性設定為FieldBinding
。調整伺服器陣列控制項的版面配置以符合您的品味。
ModelingBindingSource 是一個介面卡,可執行數個 DSL 特定的函式:
它會將更新包裝在 VMSDK 存放區交易中。
例如,當使用者從資料檢視方格刪除資料列時,一般繫結會導致交易例外狀況。
它可確保當使用者選取資料列時,[屬性] 視窗會顯示對應模型元素的屬性,而不是資料格線資料列。
資料來源與檢視之間的連結結構描述。
完成 DSL 的繫結
在 UI 專案的個別程式碼檔案中,新增下列程式碼:
using System.ComponentModel; using Microsoft.VisualStudio.Modeling; using Microsoft.VisualStudio.Modeling.Design; namespace Company.FarmApp { partial class FarmControl { public IContainer Components { get { return components; } } /// <summary>Binds the WinForms data source to the DSL model. /// </summary> /// <param name="nodelRoot">The root element of the model.</param> public void DataBind(ModelElement modelRoot) { WinFormsDataBindingHelper.PreInitializeDataSources(this); this.farmBindingSource.DataSource = modelRoot; WinFormsDataBindingHelper.InitializeDataSources(this); } } }
在 DslPackage 專案中,編輯 DslPackage\DocView.tt 以更新下列變數定義:
string viewControlTypeName = "FarmControl";
測試 DSL
DSL 解決方案現在可以建置並執行,不過您稍後可能會想要新增進一步的改善。
建置並執行方案。
在 Visual Studio 的實驗性執行個體中,開啟範例檔案。
在 FarmApp Explorer 中,開啟 [伺服器陣列] 根節點上的捷徑功能表,然後選擇 [新增山羊]。
Goat1
會出現在 [動物] 檢視中。警告
您必須使用 [伺服器陣列] 節點上的捷徑功能表,而不是 [動物] 節點。
選取 [伺服器陣列] 根節點並檢視其屬性。
在表單檢視中,變更伺服器陣列的 [Name] 或 [Size]。
當您離開表單中的每個欄位時,對應的屬性就會在 [屬性] 視窗中變更。
增強 DSL
立即更新屬性
在 FarmControl.cs 的設計檢視中,選取簡單的欄位,例如 [Name]、[Size] 或 [IsOrganic]。
在 [屬性] 視窗中,展開 [DataBindings] 節點,並且開啟 [(進階)]。
在 [格式化與進階繫結] 對話方塊的 [資料來源更新模式] 底下,選擇 [OnPropertyChanged]。
建置並執行方案。
確認當您變更欄位的內容時,伺服器陣列模型的對應屬性會立即變更。
提供新增按鈕
在 FarmControl.cs 的設計檢視中,使用工具箱在表單上建立按鈕。
編輯按鈕的名稱和文字,例如
New Sheep
。開啟按鈕後面的程式碼 (例如按兩下按鈕)。
如下所示進行編輯:
private void NewSheepButton_Click(object sender, EventArgs e) { using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep")) { elementOperations.MergeElementGroup(farm, new ElementGroup(new Sheep(farm.Partition))); t.Commit(); } } // The following code is shared with other add buttons: private ElementOperations operationsCache = null; private ElementOperations elementOperations { get { if (operationsCache == null) { operationsCache = new ElementOperations(farm.Store, farm.Partition); } return operationsCache; } } private Farm farm { get { return this.farmBindingSource.DataSource as Farm; } }
您也需要插入下列指示詞:
using Microsoft.VisualStudio.Modeling;
為「山羊」和「欄位」新增類似的按鈕。
建置並執行方案。
確認新按鈕新增為項目。 新的項目應該同時出現在 FarmApp Explorer 和適當的資料格線檢視中。
您應該能夠在資料格線檢視中編輯元素的名稱。 您也可以從該處刪除。
關於要新增元素的程式碼
對於新元素按鈕,下列替代程式碼會稍微簡單一點。
private void NewSheepButton_Click(object sender, EventArgs e)
{
using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep"))
{
farm.Animals.Add(new Sheep(farm.Partition)); ;
t.Commit();
}
}
不過,此程式碼不會設定新項目的預設名稱。 不會執行您可能已在 DSL 元素合併指示詞中定義的任何自訂合併,也不會執行任何可能已定義的自訂合併程式碼。
因此,建議您使用 ElementOperations 來建立新的元素。 如需詳細資訊,請參閱自訂元素建立和移動。