다음을 통해 공유


Windows Forms 기반 도메인 특정 언어 만들기

DSL(도메인 특정 언어) 다이어그램을 사용하는 대신 Windows Forms를 사용하여 DSL 모델의 상태를 표시할 수 있습니다. 이 항목에서는 Visual Studio 시각화 및 모델링 SDK를 사용하여 Windows Form을 DSL에 바인딩하는 과정을 안내합니다.

다음 이미지에서는 DSL 인스턴스의 모델 탐색기와 Windows Form UI를 보여 줍니다.

DSL instance in Visual Studio

Windows Forms 앱 만들기

최소 WinForm 디자이너 DSL 템플릿은 사용자 고유의 요구 사항에 맞게 수정할 수 있는 최소 DSL을 만듭니다.

  1. 최소 WinForm 디자이너 템플릿에서 DSL을 만듭니다.

    이 연습에서는 다음 이름을 가정합니다.

    • 솔루션 및 DSL 이름: FarmApp
    • 네임스페이스: Company.FarmApp
  2. 템플릿이 제공하는 초기 예제로 실험합니다.

    1. 모든 템플릿을 변형합니다.

    2. 샘플을 빌드하고 실행합니다(Ctrl+F5).

    3. Visual Studio 실험적 인스턴스에서 디버깅 프로젝트의 Sample 파일을 엽니다.

      이 파일이 Windows Forms 컨트롤에 표시됩니다.

      탐색기에 표시되는 모델의 요소를 볼 수도 있습니다.

      폼 또는 탐색기에서 일부 요소를 추가하고 다른 디스플레이에 표시되는지 확인합니다.

    Visual Studio 기본 인스턴스에서 DSL 솔루션에 대한 다음 사항을 확인합니다.

  • DslDefinition.dsl에는 다이어그램 요소가 없습니다. DSL 다이어그램을 사용하여 이 DSL의 인스턴스 모델을 보는 것이 아니기 때문입니다. 대신, Windows Form을 모델에 바인딩하고, 폼의 요소가 모델을 표시됩니다.

  • DslDslPackage 프로젝트 외에 솔루션에는 UI.라는 세 번째 프로젝트도 있습니다. UI 프로젝트에는 Windows Forms 컨트롤의 정의가 포함되어 있습니다. DslPackageUI에 따라 다르고, UIDsl에 따라 다릅니다.

  • DslPackage 프로젝트의 UI\DocView.cs에는 UI 프로젝트에 정의된 Windows Forms 컨트롤을 표시하는 코드가 포함되어 있습니다.

  • UI 프로젝트에는 DSL에 바인딩된 폼 컨트롤의 작업 샘플이 포함되어 있습니다. 그러나 DSL 정의를 변경한 경우에는 이 샘플이 작동하지 않습니다. UI 프로젝트에는 다음이 포함됩니다.

    • ModelViewControl이라는 Windows Forms 클래스.

    • ModelViewControl의 추가 부분 정의가 포함된 DataBinding.cs라는 파일. 해당 콘텐츠를 보려면 솔루션 탐색기에서 파일 바로 가기 메뉴를 열고 코드 보기를 선택합니다.

UI 프로젝트 정보

DSL 정의 파일을 업데이트하여 자체 DSL을 정의하는 경우에는 DSL을 표시하도록 UI 프로젝트의 컨트롤을 업데이트해야 합니다. DslDslPackage 프로젝트와 달리 샘플 UI 프로젝트는 DslDefinitionl.dsl에서 생성되지 않습니다. 이 연습에서는 다루지 않지만 원하는 경우 코드를 생성하는 .tt 파일을 추가할 수 있습니다.

DSL 정의 업데이트

다음 이미지는 이 연습에서 사용되는 DSL 정의입니다.

DSL definition

  1. DSL 디자이너에서 DslDefinition.dsl을 엽니다.

  2. ExampleElement 삭제

  3. ExampleModel 도메인 클래스의 이름을 Farm으로 바꿉니다.

    추가 도메인 속성으로 Int32 형식의 Size부울 형식의 IsOrganic을 지정합니다.

    참고

    루트 도메인 클래스를 삭제하고 새 루트를 만든 경우 편집기 루트 클래스 속성을 다시 설정해야 합니다. DSL 탐색기에서 편집기를 선택합니다. 그런 다음 속성 창에서 루트 클래스Farm으로 설정합니다.

  4. 명명된 도메인 클래스 도구를 사용하여 다음 도메인 클래스를 만듭니다.

    • Field - 추가 도메인 속성 Size를 지정합니다.

    • Animal - 속성 창에서 상속 한정자추상으로 설정합니다.

    참고

    명명된 도메인 클래스 도구 및 이 섹션에 언급된 다른 도구는 도구 상자 도구 창에 있습니다. 이 창은 보기>도구 상자에서 열거나 숨길 수 있습니다.

  5. 도메인 클래스 도구를 사용하여 다음 클래스를 만듭니다.

    • Sheep

    • Goat

  6. 상속 도구를 사용하여 GoatSheepAnimal에서 상속하도록 설정합니다.

  7. 포함 도구를 사용하여 FieldAnimalFarm 아래에 포함합니다.

  8. 다이어그램을 정리하는 것이 좋습니다. 중복 요소 수를 줄이려면 리프 요소의 바로 가기 메뉴에서 여기로 하위 트리 가져오기 명령을 사용합니다.

  9. 솔루션 탐색기의 도구 모음에서 모든 템플릿 변환을 선택합니다.

  10. Dsl 프로젝트를 빌드합니다.

    참고

    이 단계에서는 다른 프로젝트가 오류 없이 빌드되지 않습니다. 그러나 데이터 원본 마법사에서 해당 어셈블리를 사용할 수 있도록 Dsl 프로젝트를 빌드하려고 합니다.

UI 프로젝트 업데이트

이제 DSL 모델에 저장된 정보를 표시하는 새 사용자 정의 컨트롤을 만들 수 있습니다. 사용자 정의 컨트롤을 모델에 연결하는 가장 쉬운 방법은 데이터 바인딩을 사용하는 것입니다. ModelingBindingSource라는 데이터 바인딩 어댑터 형식은 DSL을 비 VMSDK 인터페이스에 연결하기 위해 특별히 설계되었습니다.

DSL 모델을 데이터 원본으로 정의

  1. 데이터 메뉴에서 데이터 원본 표시를 선택합니다.

    데이터 원본 창이 열립니다.

    새 데이터 원본 추가를 선택합니다. 데이터 원본 구성 마법사가 열립니다.

  2. 개체, 다음을 선택합니다.

    Dsl, Company.FarmApp을 확장하고 모델의 루트 클래스인 Farm을 선택합니다. 마침을 선택합니다.

    솔루션 탐색기의 UI 프로젝트에는 이제 Properties\DataSources\Farm.datasource가 포함되어 있습니다.

    모델 클래스의 속성 및 관계가 데이터 원본 창에 표시됩니다.

    Data sources window

모델을 폼에 연결

  1. UI 프로젝트에서 기존 .cs 파일을 모두 삭제합니다.

  2. FarmControl이라는 새 사용자 정의 컨트롤 파일을 UI 프로젝트에 추가합니다.

  3. 데이터 원본 창의 Farm 드롭다운 메뉴에서 세부 정보를 선택합니다.

    다른 속성은 기본 설정 그대로 둡니다.

  4. 디자인 뷰에서 FarmControl.cs를 엽니다.

    데이터 원본 창에서 FarmControl로 Farm을 끌어옵니다.

    각 속성에 대해 하나씩, 컨트롤 집합이 표시됩니다. 관계 속성은 컨트롤을 생성하지 않습니다.

  5. FarmBindingNavigator를 삭제합니다. 이는 FarmControl 디자이너에도 자동으로 생성되지만 이 애플리케이션에는 유용하지 않습니다.

  6. 도구 상자를 사용하여 DataGridView 인스턴스를 두 개 만들고 이름을 AnimalGridViewFieldGridView로 지정합니다.

    참고

    다른 단계는 데이터 원본 창에서 컨트롤로 Animals 및 Fields 항목을 끌어 놓는 것입니다. 이 작업을 수행하면 그리드 뷰와 데이터 원본 간에 데이터 그리드 및 바인딩이 자동으로 만들어집니다. 그러나 이 바인딩은 DSL에 대해 올바르게 작동하지 않습니다. 따라서 데이터 그리드 및 바인딩을 수동으로 만드는 것이 좋습니다.

  7. 도구 상자에 ModelingBindingSource 도구가 없는 경우 추가합니다. 데이터 탭의 바로 가기 메뉴에서 항목 선택을 선택합니다. 도구 상자 항목 선택 대화 상자의 .NET Framework 탭에서 ModelingBindingSource를 선택합니다.

  8. 도구 상자를 사용하여 ModelingBindingSource 인스턴스를 두 개 만들고 이름을 AnimalBindingFieldBinding으로 지정합니다.

  9. ModelingBindingSourceDataSource 속성을 farmBindingSource로 설정합니다.

    DataMember 속성을 Animals 또는 Fields로 설정합니다.

  10. AnimalGridViewDataSource 속성을 AnimalBinding으로 설정하고 FieldGridView에서는 FieldBinding으로 설정합니다.

  11. Farm 컨트롤의 레이아웃을 원하는 대로 조정합니다.

    ModelingBindingSource는 DSL과 관련된 몇 가지 기능을 수행하는 어댑터입니다.

  • VMSDK 저장소 트랜잭션에서 업데이트를 래핑합니다.

    예를 들어 사용자가 데이터 뷰 그리드에서 행을 삭제하면 일반 바인딩에서 트랜잭션 예외가 발생합니다.

  • 이를 통해 사용자가 행을 선택하면 속성 창에 데이터 그리드 행 대신 해당 모델 요소의 속성이 표시됩니다.

    Schema of the DSL binding

    데이터 원본과 뷰 간의 링크 스키마입니다.

DSL에 대한 바인딩 완료

  1. 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);
        }
      }
    }
    
  2. DslPackage 프로젝트에서 DslPackage\DocView.tt를 편집하여 다음 변수 정의를 업데이트합니다.

    string viewControlTypeName = "FarmControl";
    

DSL 테스트

이제 DSL 솔루션을 빌드하고 실행할 수 있습니다. 나중에 향상된 기능을 더 추가할 수 있습니다.

  1. 솔루션을 빌드하고 실행합니다.

  2. Visual Studio 실험적 인스턴스에서 샘플 파일을 엽니다.

  3. FarmApp 탐색기에서 Farm 루트 노드의 바로 가기 메뉴를 열고 Add New Goat를 선택합니다.

    Goat1Animals 보기에 표시됩니다.

    경고

    Animals 노드가 아닌 Farm 노드의 바로 가기 메뉴를 사용해야 합니다.

  4. Farm 루트 노드를 선택하고 해당 속성을 봅니다.

    폼 뷰에서 Farm의 이름 또는 크기를 변경합니다.

    폼의 각 필드에서 다른 위치로 이동하면 속성 창의 해당 속성이 변경됩니다.

DSL 향상

속성을 즉시 업데이트하도록 설정

  1. FarmControl.cs의 디자인 뷰에서 Name, Size 또는 IsOrganic 같은 단순 필드를 선택합니다.

  2. 속성 창에서 DataBindings를 확장하고 (고급) 을 엽니다.

    서식 지정 및 고급 바인딩 대화 상자의 데이터 원본 업데이트 모드에서 OnPropertyChanged를 선택합니다.

  3. 솔루션을 빌드하고 실행합니다.

    필드의 내용을 변경할 때 Farm 모델의 해당 속성이 즉시 변경되는지 확인합니다.

추가 단추 제공

  1. FarmControl.cs의 디자인 뷰에서 도구 상자를 사용하여 폼에 단추를 만듭니다.

    단추의 이름 및 텍스트를 편집합니다(예: New Sheep).

  2. 단추를 두 번 클릭하는 등의 방법으로 코드를 엽니다.

    다음과 같이 편집합니다.

    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;
    
  3. Goats 및 Fields에 대해 비슷한 단추를 추가합니다.

  4. 솔루션을 빌드하고 실행합니다.

  5. 새 단추가 항목을 추가하는지 확인합니다. 새 항목이 FarmApp 탐색기와 적절한 데이터 그리드 뷰 모두에 표시됩니다.

    데이터 그리드 뷰에서 요소의 이름을 편집할 수 있습니다. 또한 여기에서 삭제할 수도 있습니다.

    Sample data grid view

요소를 추가하는 코드

새 요소 단추의 경우 다음과 같은 대체 코드가 약간 더 간단합니다.

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를 사용하여 새 요소를 만드는 것이 좋습니다. 자세한 내용은 요소 만들기 및 이동 사용자 지정을 참조하세요.