0% found this document useful (0 votes)
407 views669 pages

T4 and Templates - TOC

Text Template Transformation Toolkit - Microsoft Documentation

Uploaded by

Joseph Riccardo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
407 views669 pages

T4 and Templates - TOC

Text Template Transformation Toolkit - Microsoft Documentation

Uploaded by

Joseph Riccardo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Table of Contents

Analyze and model your architecture


What's new for design in Visual Studio
Scenario: Change your design using visualization and modeling
Visualize code
Map dependencies across your solutions
Use code maps to debug your applications
Map methods on the call stack while debugging in Visual Studio
Find potential problems using code map analyzers
Browse and rearrange code maps
Customize code maps by editing the DGML files
Directed Graph Markup Language (DGML) reference
Create dependency diagrams from your code
Create models for your app
Dependency Diagrams: Reference
Dependency Diagrams: Guidelines
Share models and exporting diagrams
Use models in your development process
Model user requirements
Model your app's architecture
Generate and configure your app from models
Structure your modeling solution
Visual Studio Architecture Tooling Guidance
Validate your system during development
Develop tests from a model
Validate code with dependency diagrams
Extend dependency diagrams
Add commands and gestures to dependency diagrams
Add custom architecture validation to dependency diagrams
Add custom properties to dependency diagrams
Navigate and update dependency models in program code
Deploy a dependency model extension
Troubleshoot extensions for dependency diagrams
Modeling SDK for Visual Studio - Domain-Specific Languages
Getting Started with Domain-Specific Languages
Understanding Models, Classes and Relationships
How to Define a Domain-Specific Language
Customizing and Extending a Domain-Specific Language
Writing Code to Customise a Domain-Specific Language
Validation in a Domain-Specific Language
Writing User Commands and Actions
Responding to and Propagating Changes
Generating Code from a Domain-Specific Language
Customizing File Storage and XML Serialization
Deploying Domain-Specific Language Solutions
Creating a Windows Forms-Based Domain-Specific Language
Creating a WPF-Based Domain-Specific Language
Working with Domain-Specific Language Solutions
Supported Visual Studio Editions for Visualization & Modeling SDK
How to: Migrate a Domain-Specific Language to a New Version
API Reference for Modeling SDK for Visual Studio
Code Generation and T4 Text Templates
Design-Time Code Generation by using T4 Text Templates
Run-Time Text Generation with T4 Text Templates
Writing a T4 Text Template
Debugging a T4 Text Template
Guidelines for Writing T4 Text Templates
How to ... with Text Templates
Customizing T4 Text Transformation
API Reference for T4 Text Templates
Analyze and model your architecture
11/7/2017 3 min to read Edit Online

Make sure your app meets architectural requirements by using Visual Studio architecture and modeling tools to
design and model your app.
Understand existing program code more easily by using Visual Studio to visualize the code's structure,
behavior, and relationships.
Educate your team in the need for respecting architectural dependencies.
Create models at different levels of detail throughout the application lifecycle as part of your development
process.
See Scenario: Change your design using visualization and modeling.

To

Visualize code: - Visualize code


- Working with Classes and Other Types (Class Designer)
- See the code's organization and relationships by creating - Video: Understand design from code with Visual Studio
code maps. Visualize dependencies between assemblies, 2015 code maps
namespaces, classes, methods, and so on. - Video: Validate your architecture dependencies in real time
- See the class structure and members for a specific project by
creating class diagrams from code.
- Find conflicts between your code and its design by creating
dependency diagrams to validate code.

Define the architecture: - Video: Validate architecture dependencies with Visual Studio
(Channel 9)
- Define and enforce constraints on dependencies between
the components of your code by creating dependency
diagrams.

Validate your system with the requirements and - Video: Validate architecture dependencies with Visual Studio
intended design: (Channel 9)

- Validate code dependencies with dependency diagrams that


describe the intended architecture and prevent changes that
might conflict with the design.

Share models, diagrams, and code maps using Team


Foundation version control:

- Put code maps, projects, and deoendency diagrams under


Team Foundation version control so you can share them.

Customize models and diagrams: - Modeling SDK for Visual Studio - Domain-Specific
Languages
- Create your own domain-specific languages.
Generate text using T4 templates: - Code Generation and T4 Text Templates

- Use text blocks and control logic inside templates to


generate text-based files.
- T4 template build with MSBuild included in Visual Studio

To see which versions of Visual Studio support each feature, see Version support for architecture and modeling
tools

Types of Models and Their Uses


MODEL TYPE AND TYPICAL USES

Code maps

Code maps help you see the organization and relationships in your code.

Typical uses:

- Examine program code so you can better understand its structure and its dependencies, how to update it, and estimate the
cost of proposed changes.

See:

- Map dependencies across your solutions


- Use code maps to debug your applications
- Find potential problems using code map analyzers

Dependency diagram

Dependency diagrams let you define the structure of an application as a set of layers or blocks with explicit dependencies. You
can run validation to discover conflicts between dependencies in the code and dependencies described on a dependency
diagram.

Typical uses:

- Stabilize the structure of the application through numerous changes over its life.
- Discover unintentional dependency conflicts before checking in changes to the code.

See:

- Create dependency diagrams from your code


- Dependency Diagrams: Reference
- Validate code with dependency diagrams

Domain-specific language (DSL)

A DSL is a notation that you design for a specific purpose. In Visual Studio, it is usually graphical.

Typical uses:

- Generate or configure parts of the application. Work is required to develop the notation and tools. The result can be a better fit
to your domain than a UML customization.
- For large projects or in product lines where the investment in developing the DSL and its tools is returned by its use in more
than one project.

See:

- Modeling SDK for Visual Studio - Domain-Specific Languages


Where can I get more information?
Visual Studio Visualization & Modeling Tools Forum

See Also
What's new
DevOps and Application Lifecycle Management
What's new for design in Visual Studio
10/18/2017 2 min to read Edit Online

Live dependency validation


Removing unwanted dependencies is an important part of managing your technical debt. Live validation of
dependencies is now included, providing precise information about issues, and benefitting fully from the new
features in the Error list and the editor.

The authoring experience has changed to make dependency validation more discoverable and more accessible,
changing the terminology from "Layer diagram" to "Dependency diagram".
The Architecture menu now contains a command to directly create a Dependency diagram:

... and the property names of a Layer in a Dependency diagram, and their descriptions, have been changed to make
them more meaningful:
You now see the impact of your changes immediately in the analysis results for the current code in the solution
each time you save the diagram. You don't have to wait any longer for the completion of the "Validate
Dependencies" command.
For more details, see this blog post.

UML designers have been removed


The UML designers have been removed from this version of Visual Studio Enterprise.
UML diagrams are now presented as XML files
The UML Model Explorer no longer exists
Modeling project references are no longer used for dependency validation
The "Layer References" node in Solution Explorer is no longer displayed
The "Validate" build action on a Dependency (Layer) diagram is no longer used - the Build task has been
removed
The project structure is maintained for round-tripping between versions
You can still open, create, edit, and save a Dependency (Layer) diagram as XML
TFS work items linked to a Dependency (Layer) diagram are not accessible on the design surface
Back linking from to DSL or a Layer is no longer supported
UML extensibility in the Modeling SDK is no longer supported
However, support for visualizing the architecture of .NET and C++ code is available through code maps, and the
significant improvements to dependency validation described above.
If you are a significant user of the UML designers, you can continue to use Visual Studio 2015 or earlier versions
while you decide on an alternative tool for your UML needs.
For more details, see this blog post.

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.

Version support for architecture and modeling tools


Visual Studio is available in several versions. Not all of these provide support for the architecture and modelling
tools. The following table shows the availability of each tool.

FEATURE ENTERPRISE PROFESSIONAL COMMUNITY EXPRESS

Code maps Yes See Note (1) - -

Dependency Yes See Note (2) See Note (2) -


diagrams

Directed graphs Yes Yes Yes -


(DGML diagrams)

Code clone Yes - - -

Note (1): Only supports reading code maps, filtering code maps, adding new generic nodes, and creating a new
Directed Graph from a selection.
Note (2): Only supports reading dependency diagrams.
Scenario: Change your design using visualization and
modeling
10/18/2017 21 min to read Edit Online

Make sure that your software system meets users' needs by using the visualization and modeling tools in Visual
Studio. Use tools such as code maps, dependency diagrams, and class diagrams to:
To see which versions of Visual Studio support each tool, see Version support for architecture and modeling tools.
Clarify users' requirements and business processes.
Visualize and explore existing code.
Describe changes to an existing system.
Verify that the system meets its requirements.
Keep code consistent with the design.
This walkthrough:
Describes how these tools can benefit your software project.
Shows how you might use these tools, regardless your development approach, with an example scenario.
To find out more about these tools and the scenarios that they support, see:
Analyzing and Modeling Architecture
Visualize code

Scenario Overview
This scenario describes episodes from the software development lifecycles of two fictitious companies: Dinner Now
and Lucerne Publishing. Dinner Now provides a Web-based meal delivery service in Seattle. Customers can order
meals and pay for them on the Dinner Now Web site. The orders are then sent to the appropriate local restaurant
for delivery. Lucerne Publishing, a company in New York, runs several businesses both off and on the Web. For
example, they run a Web site where customers can post restaurant reviews.
Lucerne recently acquired Dinner Now and wants to make the following changes:
Integrate their Web sites by adding restaurant review capabilities to Dinner Now.
Replace Dinner Now's payment system with Lucerne's system.
Expand the Dinner Now service across the region.
Dinner Now uses SCRUM and eXtreme Programming. They have very high test coverage and very little
unsupported code. They minimize risks by creating small but working versions of a system and then adding
functionality incrementally. They develop their code over short and frequent iterations. This lets them
embrace change confidently, refactor code frequently, and avoid "big design up front".
Lucerne maintains a vastly larger and complex collection of systems, some of which are more than 40 years
old. They are very cautious about making changes because of the complexity and scope of legacy code. They
follow a more rigorous development process, preferring to design detailed solutions and to document the
design and changes that occur during development.
Both teams use modeling diagrams in Visual Studio to help them develop systems that meet the users'
needs. They use Team Foundation Server alongside other tools to help them plan, organize, and manage
their work.
For more information about Team Foundation Server, see:
Planning and tracking work
Testing, validating, and checking in updated code

Roles of Architecture and Modeling Diagrams in Software Development


The following table describes roles that these tools can play during multiple and various stages of the software
development lifecycle:

USER BUSINESS SYSTEM CODE


REQUIREMENTS PROCESS ARCHITECTURE & VISUALIZATION &
MODELING MODELING DESIGN EXPLORATION VERIFICATION

Domain-Specific Yes Yes Yes


Language (DSL)
diagram

Dependency Yes Yes Yes


diagram, layer
validation

Code map Yes Yes Yes

Class Designer Yes


(code-based)

To draw dependency diagrams, you must create a modeling project as part of an existing solution or a new one.
These diagrams must be created in the modeling project. Items on dependency diagrams are located in the
modeling project, but they are not stored in the common model. Code maps and .NET class diagrams created from
code exist outside the modeling project.
See:
Create dependency diagrams from your code
Map dependencies across your solutions
How to: Add Class Diagrams to Projects (Class Designer)
Modeling SDK for Visual Studio - Domain-Specific Languages

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.

Both teams also use dependency validation to make sure that code under development remains consistent with the
design.
See:
Keeping Code Consistent with the Design
Describe the Logical Architecture: Dependency Diagrams
Validate code with dependency diagrams

NOTE
Some versions of Visual Studio support dependency validation and read-only versions of code maps for visualization
and modeling. To see which versions of Visual Studio support this feature, see Version support for architecture and
modeling tools.

Understanding and Communicating Information about the System


There is no prescribed order for using the Visual Studio modeling diagrams, so you can use them as they fit with
your needs or approach. Usually, teams revisit their models iteratively and frequently throughout a project. Each
diagram offers particular strengths to help you understand, describe, and communicate different aspects of the
system under development.
Dinner Now and Lucerne communicate with each another and with project stakeholders by using diagrams as their
common language. For example, Dinner Now uses diagrams to perform these tasks:
Visualize existing code.
Communicate with Lucerne about new or updated user stories.
Identify changes that are required to support new or updated user stories.
Lucerne uses diagrams to perform these tasks:
Learn about the Dinner Now business process.
Understand the design of the system.
Communicate with Dinner Now about new or updated user requirements.
Document updates to the system.
The diagrams are integrated with Team Foundation Server so the teams can plan, manage, and track their
work more easily. For example, they use models to identify test cases and development tasks and to
estimate their work. Lucerne links Team Foundation Server work items to model elements so that they can
monitor progress and make sure that the system meets the users' requirements. For example, they link use
cases to test case work items so they can see that use cases are fulfilled when all the tests pass.
Before teams check in their changes, they validate the code against the tests and the design by running
builds that include dependency validation and automated tests. This helps make sure that the updated code
does not conflict with the design and break previously working functionality.
See:
Identifying changes to the existing system
Keeping code consistent with the design
General tips for creating and using models
Planning and tracking work
Testing, validating, and checking in updated code
Identifying Changes to the Existing System
Dinner Now must estimate the cost of meeting the new requirement. This depends partly on how much this change
will affect other parts of the system. To help them understand this, one of the Dinner Now developers creates these
maps and diagrams from existing code:
MAP OR DIAGRAM SHOWS

Code map Dependencies and other relationships in code.

See: For example, Dinner Now might start by reviewing assembly


code maps for an overview of the assemblies and their
- Map dependencies across your solutions dependencies. They can drill into the maps to explore the
- Browse and rearrange code maps namespaces and classes in those assemblies.
- Customize code maps by editing the DGML files
Dinner Now can also create maps to explore particular areas
and other kinds of relationships in the code. They use Solution
Explorer to find and select the areas and relationships that
interest them.

Code-based class diagram Existing classes in code

See How to: Add Class Diagrams to Projects (Class Designer).

For example, the developer creates a code map. She adjusts its scope to focus on the areas that will be affected by
the new scenario. These areas are selected and highlighted on the map:

Namespace code map


The developer expands the selected namespaces to see their classes, methods, and relationships:
Expanded namespace code map with visible cross-group links
The developer examines the code to find the affected classes and methods. To see the effects of each change as you
make them, regenerate code maps after each change. See Visualize code.
To describe changes to other parts of the system, such as components or interactions, the team might draw these
elements on whiteboards. They might also draw the following diagrams in Visual Studio so that the details can be
captured, managed, and understood by both teams:

DIAGRAMS DESCRIBES

Code-based class diagram Existing classes in code.

See How to: Add Class Diagrams to Projects (Class Designer).

Keeping Code Consistent with the Design


Dinner Now must make sure that the updated code stays consistent with the design. They create dependency
diagrams that describe the layers of functionality in the system, specify the permitted dependencies between them,
and associate solution artifacts to those layers.

DIAGRAM DESCRIBES

Dependency diagram The logical architecture of the code.

See: A dependency diagram organizes and maps the artifacts in a


Visual Studio solution to abstract groups called layers. These
- Create dependency diagrams from your code layers identify the roles, tasks, or functions that these artifacts
- Dependency Diagrams: Reference perform in the system.
- Dependency Diagrams: Guidelines
- Validate code with dependency diagrams Layer diagrams are useful for describing the intended design
of the system and validating evolving code against that
design.

To create layers, drag items from Solution Explorer, code maps,


Class View, and Object Browser. To draw new layers, use the
toolbox or right-click the diagram surface.

To view existing dependencies, right-click the layer diagram


surface, and then click Generate Dependencies. To specify
intended dependencies, draw new dependencies.

For example, the following dependency diagram describes dependencies between layers and the number of
artifacts that are associated with each layer:

Dependency Diagram
To make sure that conflicts with the design do not occur during code development, the teams uses dependency
validation on builds that are run on Team Foundation Build. They also create a custom MSBuild task to require
dependency validation in their check-in operations. They use build reports to collect validation errors.
See:
Define your build process
Use a gated check-in build process to validate changes
Customize your build process template
General Tips for Creating and Using Models
Most diagrams consist of nodes that are connected by lines. For each diagram type, the toolbox provides
different kinds of nodes and lines.
To open the toolbox, on the View menu, click Toolbox.
To create a node, drag it from the toolbox to the diagram. Certain kinds of nodes must be dragged onto
existing nodes. For example, on a component diagram, a new port must be added to an existing component.
To create a line or a connection, click the appropriate tool in the toolbox, click the source node, and then click
the target node. Some lines can be created only between certain kinds of nodes. When you move the pointer
over a possible source or target, the pointer indicates whether you can create a connection.
Planning and Tracking Work
Visual Studio modeling diagrams are integrated with Team Foundation Server so that you can plan, manage, and
track work more easily. Both teams use models to identify test cases and development tasks and to estimate their
work. Lucerne creates and links Team Foundation Server work items to model elements, such as use cases or
components. This helps them monitor their progress and trace their work back to the users' requirements. This
helps them make sure that their changes continue to meet those requirements.
As their work progresses, the teams update their work items to reflect the time that they spent on their tasks. They
also monitor and report status on their work by using the following Team Foundation Server features:
Daily burndown reports that show whether they will complete the planned work in the expected time. They
generate other similar reports from Team Foundation Server to track the progress of bugs.
An iteration worksheet that uses Microsoft Excel to help the team monitor and balance the workload
between its members. This worksheet is linked to Team Foundation Server and provides focus for discussion
during their regular progress meetings.
A development dashboard that uses Office Project to keep the team informed about important project
information.
See:
Track work using Visual Studio Team Services or Team Foundation Server
Charts, dashboards, and reports for Visual Studio ALM
Create your backlog and tasks using Project
Testing, Validating, and Checking In Code
As the teams complete each task, they check their code into Team Foundation version control and receive
reminders from Team Foundation Server, if they forget. Before Team Foundation Server accepts their check-ins, the
teams run unit tests and dependency validation to verify the code against their test cases and the design. They use
Team Foundation Server to run builds, automated unit tests, and dependency validation regularly. This helps make
sure that the code meets the following criteria:
It works.
It does not break previously working code.
It does not conflict with the design.
Dinner Now has a large collection of automated tests, which Lucerne can reuse because almost all still apply.
Lucerne can also build on these tests and add new ones to cover new functionality. Both also use Visual
Studio to run manual tests.
To make sure that the code conforms to the design, the teams configure their builds in Team Foundation
Build to include dependency validation. If any conflicts occur, a report is generated with the details.
See:
Testing the application
Validate your system during development
Use version control
Build the application

Updating the System Using Visualization and Modeling


Lucerne and Dinner Now must integrate their payment systems. The following sections show the modeling
diagrams in Visual Studio help them perform this task:
Visualize Existing Code: Code Maps
Define a Glossary of Types: Class Diagrams
Describe the Logical Architecture: Dependency Diagrams
See:
Visualize code
Use models in your development process
Model your app's architecture
Visualize Existing Code: Code Maps
Code maps show the current organization and relationships in the code. Items are represented by nodes on the
map, and relationships are represented by links. Code maps can help you perform the following kinds of tasks:
Explore unfamiliar code.
Understand where and how a proposed change might affect existing code.
Find areas of complexity, natural dependencies or patterns, or other areas that might benefit from
improvement.
For example, Dinner Now must estimate the cost of updating the PaymentProcessing component. This
depends partly on how much this change will affect other parts of the system. To help them understand this,
one of the Dinner Now developers generates code maps from the code and adjusts the scope focus on the
areas that might be affected by the change.
The following map shows the dependencies between the PaymentProcessing class and other parts of the
Dinner Now system, which appear selected:
Code map for Dinner Now payment system
The developer explores the map by expanding the PaymentProcessing class and selecting its members to
see the areas that are potentially affected:

Methods inside PaymentProcessing class and their dependencies


They generate the following map for the Lucerne Payment System to inspect its classes, methods, and
dependencies. The team sees that the Lucerne system might also require work to interact with the other
parts of Dinner Now:
Code map for Lucerne Payment System
Both teams work together to determine the changes that are required to integrate the two systems. They
decide to refactor some of the code so that it will be easier to update. The PaymentApprover class will move
to the DinnerNow.Business namespace and will require some new methods. The Dinner Now classes that
handle transactions will have their own namespace. The teams create and use work items to plan, organize,
and track their work. They link the work items to model elements where it is useful.
After reorganizing the code, the teams generate a new code map to see the updated structure and
relationships:

Code map with reorganized code


This map shows that the PaymentApprover class is now in the DinnerNow.Business namespace and has
some new methods. The Dinner Now transaction classes now have their own PaymentSystem namespace,
which makes it easier to deal with that code later.
Creating a Code Map
For a quick overview of source code, follow these steps to generate a code map:
On the Architecture menu, click Generate Code Map For Solution.
For a quick overview of compiled code, create a blank code map, and then drag assembly files or binary files
to the map surface.
To explore specific code or solution items, use Solution Explorer to select items and relationships that you
want to visualize. You can then either generate a new map or add selected items to an existing map. See
Map dependencies across your solutions.
To help you explore the map, rearrange the layout so that it suits the kinds of tasks that you want to
perform.
For example, to visualize layering in the code, select a tree layout. See Browse and rearrange code maps.
Summary: Strengths of Code Maps
Code maps help you:
Learn about the organization and relationships in existing code.
Identify areas that might be affected by a proposed change.
Find areas of complexity, patterns, layers, or other areas that you could improve to make the code easier to
maintain, change, and reuse.
Relationship to Other Diagrams

DIAGRAM DESCRIBES

Dependency diagram The logical architecture of the system. Use dependency


validation to make sure that the code stays consistent with
the design.

To help you identify existing dependencys or intended


dependencys, create a code map and group related items. To
create a dependency diagram, see:

- Create dependency diagrams from your code


- Dependency Diagrams: Guidelines

Class diagram (code-based) Existing classes in code for a specific project.

To visualize and modify an existing class in code, use Class


Designer.

See How to: Add Class Diagrams to Projects (Class Designer).

Define a Glossary of Types: Class Diagrams


Class diagrams define the entities, terms, or concepts that participate in the system and their relationships with one
another. For example, you can use these diagrams during development to describe the attributes and operations
for each class, regardless of their implementation language or style.
To help Lucerne describe and discuss the entities that participate in the Process Payment use case, they draw the
following class diagram:
Process Payment entities on a class diagram
This diagram shows that a Customer can have many orders and different ways to pay for orders. BankAccount and
CreditCard both inherit from Payment.
During development, Lucerne uses the following class diagram to describe and discuss the details of each class:

Process Payment details on the class diagram


Drawing a Class Diagram
A class diagram has the following major features:
Types such as classes, interfaces, and enumerations:
A class is the definition of objects that share specific structural or behavioral characteristics.
An interface defines a part of the externally visible behavior of an object.
An enumeration is a classifier that contains a list of literal values.
Attributes are values of a certain type that describe each instance of a classifier. A classifier is a general name
for types, components, use cases, and even actors.
Operations are methods or functions that instances of a classifier can perform.
An association indicates some kind of relationship between two classifiers.
An aggregation is an association that indicates a shared ownership between classifiers.
A composition is an association that indicates a whole-part relationship between classifiers.
To show aggregations or compositions, set the Aggregation property on an association. Shared
shows aggregations and Composite shows compositions.
A dependency indicates that changing the definition of one classifier might change the definition of another
classifier.
A generalization indicates that a specific classifier inherits part of its definition from a general classifier. A
realization indicates that a class implements the operations and attributes offered by an interface.
To create these relationships, use the Inheritance tool. Alternatively, a realization can be represented as a
lollipop.
Packages are groups of classifiers, associations, lifelines, components, and other packages. Import
relationships indicate that one package includes all definitions of another package.
As a starting point to explore and discuss existing classes, you can use Class Designer to create class
diagrams from code.
How to: Add Class Diagrams to Projects (Class Designer)
Summary: Strengths of Class Diagrams
Class diagrams help you define:
A common glossary of terms to use when discussing the users' needs and the entities that participate in the
system. See Model user requirements.
Types that are used by parts of the system, such as components, regardless of their implementation. See
Model your app's architecture.
Relationships, such as dependencies, between types. For example, you can show that one type can be
associated with multiple instances of another type.
Relationship to Other Diagrams

DIAGRAM DESCRIPTION

Dependency diagram Define the logical architecture of the system as it relates to


classes.

Use dependency validation to make sure that the code stays


consistent with the design.

See:

- Create dependency diagrams from your code


- Dependency Diagrams: Reference
- Dependency Diagrams: Guidelines
- Validate code with dependency diagrams

Code map Visualize the organization and relationships in existing code.

To identify classes, their relationships, and their methods,


create a code map that shows those elements.

See:

- Map dependencies across your solutions

Describe the Logical Architecture: dependency Diagrams


Dependency diagrams describe the logical architecture of a system by organizing the artifacts in your solution into
abstract groups, or layers. Artifacts can be many things, such as namespaces, projects, classes, methods, and so on.
Layers represent and describe the roles or tasks that the artifacts perform in the system. You can also include layer
validation in your build and check-in operations to make sure that the code stays consistent with its design.
To keep the code consistent with the design, Dinner Now and Lucerne use the following dependency diagram to
validate their code as it evolves:
Dependency diagram for Dinner Now integrated with Lucerne
The layers on this diagram link to the corresponding Dinner Now and Lucerne solution artifacts. For example, the
Business layer links to the DinnerNow.Business namespace and its members, which now include the
PaymentApprover class. The Resource Access layer links to the DinnerNow.Data namespace. The arrows, or
dependencies, specify that only the Business layer can use the functionality in the Resource Access layer. As the
teams update their code, layer validation is performed regularly to catch conflicts as they occur and to help the
teams resolve them promptly.
The teams work together to incrementally integrate and test the two systems. They first make sure that
PaymentApprover and the rest of Dinner Now work with one another successfully before they deal with
PaymentProcessing.
The following code map shows the new calls between the Dinner Now and PaymentApprover:

Code map with updated method calls


After they confirm that the system works as expected, Dinner Now comments out the PaymentProcessing code. The
layer validation reports are clean, and the resulting code map shows that no more PaymentProcessing
dependencies exist:
Code map without PaymentProcessing
Drawing a Dependency Diagram
A dependency diagram has the following major features:
Layers describe logical groups of artifacts.
A link is an association between a layer and an artifact.
To create layers from artifacts, drag items from Solution Explorer, code maps, Class View, or Object Browser.
To draw new layers and then link them to artifacts, use the toolbox or right-click the diagram surface to
create the layers, and then drag items to those layers.
The number on a layer shows the number of artifacts that are linked to the layer. These artifacts can be
namespaces, projects, classes, methods, and so on. When you interpret the number of artifacts on a layer,
remember the following:
If a layer links to an artifact that contains other artifacts, but the layer does not link directly to the
other artifacts, then the number includes only the linked artifact. However, the other artifacts are
included for analysis during layer validation.
For example, if a layer is linked to a single namespace, then the number of linked artifacts is 1, even if
the namespace contains classes. If the layer also has links to each class in the namespace, then the
number will include the linked classes.
If a layer contains other layers that are linked to artifacts, then the container layer is also linked to
those artifacts, even though the number on the container layer does not include those artifacts.
To see the artifacts that are linked to a layer, right-click the dependency, and then click View Links to
open Layer Explorer.
A dependency indicates that one layer can use the functionality in another layer, but not vice versa. A
bidirectional dependency indicates that one layer can use the functionality in another layer, and vice versa.
To display existing dependencies on the dependency diagram, right-click the diagram surface, and then click
Generate Dependencies. To describe intended dependencies, draw new ones.
See:
Create dependency diagrams from your code
Dependency Diagrams: Reference
Dependency Diagrams: Guidelines
Validate code with dependency diagrams
Summary: Strengths of Dependency Diagrams
Dependency diagrams help you:
Describe the logical architecture of a system according to the functionality of its artifacts.
Make sure that code under development conforms to the specified design.
Relationship to Other Diagrams

DIAGRAM DESCRIPTION

Code map Visualize the organization and relationships in existing code.

To create layers, generate a code map, and then group items


on the map as potential layers. Drag the groups from the map
to the dependency diagram.

See:

- Map dependencies across your solutions


- Browse and rearrange code maps

External Resources
CATEGORY LINKS

Forums - Visual Studio Visualization & Modeling Tools


- Visual Studio Visualization & Modeling SDK (DSL Tools)

See Also
Visualize code
Use models in your development process
Use models in Agile development
Validate your system during development

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.
Visualize code
10/18/2017 1 min to read Edit Online

You can use the visualization and modeling tools in Visual Studio to help you understand existing code and
describe your application. This lets you visually learn how your changes might affect the code and help you assess
the work and risks that result from those changes. For example:
To understand the relationships in your code, map those relationships visually.
To describe your system's architecture and keep the code consistent with its design, create dependency
diagrams and validate code against these diagrams.
To describe class structures, create class diagrams.
These tools also help you communicate more easily with the people involved with your project.
To see which versions of Visual Studio support each feature, see Version support for architecture and
modeling tools

What do you want to do?

Understand code and its relationships: - Map dependencies across your solutions
- Use code maps to debug your applications
Map relationships between specific pieces of code. - Find potential problems using code map analyzers
- Map methods on the call stack while debugging
See an overview of the relationships in your code for the
entire solution.

Note: In this release of Visual Studio, the term code map is


used in place of dependency graph.

Understand class structures: How to: Add Class Diagrams to Projects (Class Designer)

Visualize the structure of classes in a project by creating class


diagrams from code.

Describe the high-level system design and validate code - Create dependency diagrams from your code
against this design: - Dependency Diagrams: Reference
- Dependency Diagrams: Guidelines
Describe the high-level system design and its intended - Validate code with dependency diagrams
dependencies by creating dependency diagrams. Validate
code against this design to make sure dependencies in code
remain consistent with the design.

External Resources
CATEGORY LINKS

Forums - Visual Studio Visualization & Modeling Tools


- Visual Studio Visualization & Modeling SDK (DSL Tools)

Blogs Visual Studio ALM + Team Foundation Server Blog


CATEGORY LINKS

Technical Articles and Journals MSDN Architecture Forum

See Also
Scenario: Change your design using visualization and modeling
Analyzing and Modeling Architecture
Model your app's architecture
Use models in your development process

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK
are installed automatically when you install specific features of Visual Studio. For more details, see this blog
post.
Map dependencies across your solutions
10/18/2017 16 min to read Edit Online

When you want to understand dependencies across your code, visualize them by creating code maps. This helps
you see how the code fits together without reading through files and lines of code.

Here are some videos:


Understand your code dependencies through visualization
Visualize the impact of a change
Understanding complex code with code maps

Get started with code maps


To use code maps you'll need either:
Visual Studio Enterprise: Create code maps from the code editor, Solution Explorer, Class View, or Object
Browser.
Visual Studio Professional: Open code maps, make limited edits, and navigate code.

WARNING
Before you share maps created in Visual Studio Enterprise with others who use Visual Studio Professional, make sure that
all the items on the map (such as hidden items, expanded groups, and cross-group links) are made visible.

You can map dependencies for code in these languages:


Visual C# .NET or Visual Basic .NET in a solution or assemblies (.dll or .exe)
Native or managed C or C++ code in Visual C++ projects, header files (.h or #include ), or binaries
X++ projects and assemblies made from .NET modules for Microsoft Dynamics AX
Note: For projects other than C# or Visual Basic .NET, there are fewer options for starting a code map or
adding items to an existing code map. For example, you cannot right-click an object in the text editor of a
C++ project and add it to a code map. However, you can drag and drop individual code elements or files
from Solution Explorer, Class View, and Object Browser.
To see the overall dependencies across your solution
1. Open the Architecture menu.
2. If you just opened the solution and haven't yet built it, or if your code has changed since the last time you
built it, choose Generate Code Map for Solution.
3. If your code hasn't changed since the last time you built it, choose Generate Code Map for Solution
Without Building to get faster performance when creating the map.
4. See overall dependencies to understand how you can use code maps to view the overall dependencies
across your solution.
To see specific dependencies within your solution
1. With your solution loaded, open Solution Explorer.
2. Select all the projects, assembly references, folders, files, types, or members that you want to map.
3. On the Solution Explorer toolbar, choose Show on Code Map . Or open the shortcut menu and
choose Show on Code Map. You can also drag items from Class View or Object Browser into a new or
an existing code map.
4. See specific dependencies to understand how you can use code maps to view specific dependencies
within your solution.
To add a new empty code map to your solution
1. In Solution Explorer, open the shortcut menu for your top-level solution node. Choose Add then
choose New Item.
2. Under Installed, choose General.
3. In the right pane, choose Directed Graph Document and then choose Add.
You now have a blank map, which appears in your solution's Solution Items folder.
To create a new empty code map without adding it to your solution
1. Open the Architecture menu and choose New Code Map.
- or -
2. Open the File menu and choose New then choose File.
3. Under Installed, choose General.
4. In the right pane, choose Directed Graph Document and then choose Open.
You now have a blank map, which does not appear in your solution's folders.

See overall dependencies


See dependencies across your solution
1. On the Architecture menu, choose Generate Code Map for Solution.
You get a map that shows the top-level assemblies and aggregated links between them. The wider the
aggregate link, the more dependencies it represents.
2. Use the Legend button on the code map toolbar to show or hide the list of project type icons (such as
Test, Web, and Phone Project), code items (such as Classes, Methods, and Properties), and relation types
(such as Inherits From, Implements, and Calls).

This example solution contains Solution Folders (Tests and Components), Test Projects, Web Projects,
and assemblies. By default, all containment relationships appear as groups, which you can expand and
collapse. The Externals group contains anything outside your solution, including platform dependencies.
External assemblies show only those items that are used. By default, system base types are hidden on the
map to reduce clutter.
3. To drill down into the map, expand the groups that represent projects and assemblies. You can expand
everything by pressing CTRL+A to select all the nodes and then choosing Group, Expand from the
shortcut menu.
4. However, this may not be useful for a large solution. In fact, for complex solutions, memory limitations
may prevent you from expanding all the groups. Instead, to see inside an individual node, expand it.
Move your mouse pointer on top of the node and then click the chevron (down arrow) when it appears.

Or use the keyboard by selecting the item then pressing the plus key (+). To explore deeper levels of
code, do the same for namespaces, types, and members.

TIP
For more details of working with code maps using the mouse, keyboard, and touch, see Browse and rearrange
code maps.

5. To simplify the map and focus on individual parts, choose Filters on the code map toolbar and select just
the types of nodes and links you are interested in. For example, you can hide all the Solution Folder and
Assembly containers.
You can also simplify the map by hiding or removing individual groups and items from the map, without
affecting the underlying solution code.
6. To see the relationships between items, select them in the map. The colors of the links indicate the types
of relationship, as shown in the Legend pane.

In this example, the purple links are calls, the dotted links are references, and the light blue links are field
access. Green links can be inheritance, or they may be aggregate links that indicate more than one type
of relationship (or category).
TIP
If you see a green link, it might not mean there's just an inheritance relationship. There might also be method
calls, but these are hidden by the inheritance relationship. To see specific types of links, use the checkboxes in the
Filters pane to hide the types you aren't interested in.

7. To get more information about an item or link, move the pointer on top of it until a tooltip appears. This
shows details of a code element or the categories that a link represents.

8. To examine items and dependencies represented by an aggregate link, first select the link and then open
its shortcut menu. Choose Show Contributing Links (or Show Contributing Links on New Code
Map). This expands the groups at both ends of the link and shows only those items and dependencies
that participate in the link.
9. To focus in on specific parts of the map, you can continue to remove items you aren't interested in. For
example, to drill into class and member view, simply filter all the namespace nodes in the Filters pane.
10. Another way to focus in on a complex solution map is to generate a new map containing selected items
from an existing map. Hold CTRL while selecting the items you want to focus on, open the shortcut
menu, and choose New Graph from Selection.
11. The containing context is carried over to the new map. Hide Solution Folders and any other containers
you don't want to see using the Filters pane.

12. Expand the groups and select items in the map to view the relationships.
See also:
Browse and rearrange code maps
Customize code maps by editing the DGML files
Find potential problems in your code by running an analyzer.
See dependencies across assemblies or binaries
1. Create an empty code map, or open an existing code map (.dgml file).
2. Drag the assemblies or binaries you want to map from outside Visual Studio onto the map. For example,
drag assemblies or binaries from Windows Explorer or File Explorer.

NOTE
You can drag assemblies or binaries from Windows Explorer or File Explorer only if you are running it and Visual Studio at
the same User Access Control (UAC) permissions level. For example, if UAC is turned on and you are running Visual
Studio as Administrator, Windows Explorer or File Explorer will block the dragging operation. To work around this, make
sure that both are running with the same permission level, or turn UAC off.

See specific dependencies


For example, suppose you have a code review to perform in some files with pending changes. To see the
dependencies in those changes, you can create a code map from those files.
See specific dependencies in your solution
1. Open Solution Explorer. Select the projects, assembly references, folders, files, types, and members that
interest you. To find items that have dependencies on types or members, open the type or member's
shortcut menu from Solution Explorer. Choose the dependency type, and then select the results.
2. Map your items and their members. On the Solution Explorer toolbar click Show on Code Map .
3. The map shows the selected items within their containing assemblies.

You can also drag items from Solution Explorer, Class View, or Object Browser to a blank or an existing
code map. To create a blank map, see Create an empty code map. To include the parent hierarchy for
your items, press and hold the CTRL key while you drag items, or use the Include Parents button on the
code map toolbar to specify the default action.
NOTE
When you add items from a project that's shared across multiple apps, like Windows Phone or Windows Store,
those items appear on the map with the currently active app project. If you change context to another app
project and add more items from the shared project, those items now appear with the newly active app project.
Operations that you perform with an item on the map apply only to those items that share the same context.

4. To explore items, expand them. Move the mouse pointer on top of an item, then click the chevron (down
arrow) icon when it appears.

To expand all items, select them using CTRL+A, then open the shortcut menu for the map and choose
Group, Expand. However, this option isn't available if expanding all groups creates an unusable map or
memory issues.
5. Continue to expand items you are interested in, right down to the class and member level if required.

To see members that are in the code but don't appear on the map, click the Refetch Children icon in
the top left corner of a group.
6. To see more items related to those on the map, select one and choose Show Related on the code map
toolbar, then select the type of related items to add to the map. Alternatively, select one or more items,
open the shortcut menu, and then choose the Show... option for the type of related items to add to the
map. For example:
For an assembly, choose:

Show Assemblies This References Add assemblies that this assembly references. External
assemblies appear in the Externals group.

Show Assemblies Referencing This Add assemblies in the solution that reference this
assembly.

For a namespace, choose Show Containing Assembly, if it's not visible.


For a class or interface, choose:

Show Base Types For a class, add the base class and the implemented
interfaces.

For an interface, add the base interfaces.

Show Derived Types For a class, add the derived classes.

For an interface, add the derived interfaces and the


implementing classes or structs.

Show Types This References Add all classes and their members that this class uses.

Show Types Referencing This Add all classes and their members that use this class.

Show Containing Namespace Add the parent namespace.

Show Containing Namespace and Assembly Add the parent container hierarchy.

Show All Base Types Add the base class or interface hierarchy recursively.

Show All Derived Types For a class, add all the derived classes recursively.

For an interface, add all the derived interfaces and


implementing classes or structs recursively.

For a method, choose:

Show Methods This Calls Add methods that this method calls.

Show Fields This References Add fields that this method references.

Show Containing Type Add the parent type.


Show Containing Type, Namespace, and Assembly Add the parent container hierarchy.

Show Overridden Methods For a method that overrides other methods or


implements an interface's method, add all the abstract
or virtual methods in base classes that are overridden
and, if any, the interface's method that is implemented.

For a field or property, choose:

Show Containing Type Add the parent type.

Show Containing Type, Namespace, and Assembly Add the parent container hierarchy.

7. The map shows the relationships. In this example, the methods called by the Find method, and their
location in the solution or externally.
8. To simplify the map and focus on individual parts, choose Filters on the code map toolbar and select just
the types of nodes and links you are interested in. For example, turn off display of Solution Folders,
Assemblies, and Namespaces.
See dependencies between C and C++ source files and header files
If you want to create more complete maps for C++ projects, set the browse information compiler option (/FR)
on those projects. Otherwise, a message appears and prompts you to set this option. If you select OK, this sets
the option for just the current map. You can choose to hide the message for all later maps. If you hide this
message, you can make it appear again. Set the following registry key to 0 or delete the key:
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0\NativeProvider : AutoEnableSbr
When you open a solution that contains Visual C++ projects, it might take some time to update the IntelliSense
database. During this time, you might not be able to create code maps for header (.h or #include ) files until the
IntelliSense database finishes updating. You can monitor the update progress in the Visual Studio status bar. To
resolve issues or messages that appear because certain IntelliSense settings are disabled, see Troubleshoot
maps for C and C++ code.
To see dependencies between all source files and header files in your solution, on the Architecture
menu, choose Generate Graph of Include Files.
To see dependencies between the currently open file and related source files and header files, open
either the source file or the header file. Open the file shortcut menu anywhere inside the file. Choose
Generate Graph of Include Files.

Troubleshoot maps for C and C++ code


These items aren't supported for C and C++ code:
Base types don't appear on maps that include the parent hierarchy.
Most Show menu items aren't available for C and C++ code.
These issues might happen when you create code maps for C and C++ code:

ISSUE POSSIBLE CAUSE RESOLUTION

The code map failed to generate. No projects in the solution were built Fix the build errors that occurred and
successfully. then regenerate the map.

Visual Studio becomes unresponsive The program database (.pdb) file might Rebuild the solution and then try
when you try to generate a code map be corrupted. again.
from the Architecture menu.
A .pdb file stores debugging
information, such as type, method,
and source file information.

Certain settings for the IntelliSense Certain IntelliSense settings might be Turn on the settings to enable them.
browsing database are disabled. disabled in the Visual StudioOptions
dialog box. See Options, Text Editor, C/C++,
Advanced.

The message Unknown Methods The binary file might not have a base Turn on the /FIXED:NO option in the
appears on a method node. relocation table. linker.

This issue occurs because the name of


the method cannot be resolved.
ISSUE POSSIBLE CAUSE RESOLUTION

The program database (.pdb) file might Turn on the /DEBUG option in the
not be built. linker.

A .pdb file stores debugging


information, such as type, method,
and source file information.

Cannot open or find the .pdb file in Make sure that the .pdb file exists in
the expected locations. the expected locations.

Debug information has been stripped If the /PDBSTRIPPED option was used
from the .pdb file. in the linker, include the complete .pdb
file instead.

The caller is not a function and is When the caller is a thunk, try using
either a thunk in the binary file or a _declspec(dllimport) to avoid the
pointer in the data section. thunk.

Make code maps render more quickly


When you generate a map for the first time, Visual Studio indexes all the dependencies that it finds. This process
might take some time, especially for large solutions, but will improve performance later. If your code changes,
Visual Studio re-indexes just the updated code. To minimize the time taken for the map to finish rendering,
consider the following:
Map only the dependencies that interest you.
Before you generate the map for an entire solution, reduce the solution scope.
Turn off automatic build for the solution with the Skip Build button on the code map toolbar.
Turn off automatic adding of parent items with the Include Parents button on the code map toolbar.
Edit the code map file directly to remove nodes and links you don't need. Changing the map doesn't
affect the underlying code. See Customize code maps by editing the DGML files.

Although Visual Studio can run with 1 GB of memory, we recommended that your computer have at
least 2 GB of memory to avoid long delays while Visual Studio creates the code index and generates the
map.
It might take more time to create maps or add items to a map from Solution Explorer when a project
item's Copy to Output Directory property is set to Copy Always. This might cause issues with
incremental builds and Visual Studio to rebuild the project each time. To increase performance, change
this property to Copy if newer or PreserveNewest . See Incremental Builds.
The completed map will show dependencies only for successfully-built code. If build errors occur for
certain components, these errors appear on the map. Make sure that a component actually builds and
has dependencies on it before you make architectural decisions based on the map.
Share code maps
Share the map with other Visual Studio users
Use the File menu to save the map.
-or-
To save the map as part of specific project, on the map toolbar, choose Share, Move <CodeMapName>.dgml
into, and then choose the project where you want to save the map.

Visual Studio saves the map as a .dgml file that you can share with other users of Visual Studio Enterprise and
Visual Studio Professional.

NOTE
Before you share a map with those who use Visual Studio Professional, make sure to expand any groups, show hidden
nodes and cross-group links, and retrieve any deleted nodes that you want others to see on your map. Otherwise, other
users won't be able to see these items.
The following error might occur when you save a map that is in a modeling project or was copied from a modeling
project to another location:
"Cannot save fileName outside the project directory. Linked items are not supported."
Visual Studio shows the error, but creates the saved version anyway. To avoid the error, create the map outside the
modeling project. You can then save it to the location that you want. Just copying the file to another location in the
solution, and then trying to save it will not work.

Export the map as an image so you can copy it into other applications, such as Microsoft Word or PowerPoint
1. On the code map toolbar, choose Share, Email as Image or Copy Image.
2. Paste the image into another application.
Export the map as an XPS file so you can see it in XML or XAML viewers like Internet Explorer
1. On the code map toolbar, choose Share, Email As Portable XPS or Save As Portable XPS.
2. Browse to where you want to save the file.
3. Name the code map. Make sure that the Save as type box is set to XPS files (*.xps). Choose Save.
What else can I do?
Use code maps to debug your applications
Map methods on the call stack while debugging
Find potential problems using code map analyzers
Browse and rearrange code maps
Customize code maps by editing the DGML files
Use code maps to debug your applications
10/18/2017 4 min to read Edit Online

Code maps can help you avoid getting lost in large code bases, unfamiliar code, or legacy code. For example,
when you're debugging, you might have to look at code across many files and projects. Use code maps to
navigate around pieces of code and understand the relationships between them. That way, you don't have to keep
track of this code in your head, or draw a separate diagram. So, when your work is interrupted, code maps help
refresh your memory about the code you're working on.

A green arrow shows where your cursor appears in the editor


For details of the commands and actions you can use when working with code maps, see Browse and rearrange
code maps.

Understand the problem


Suppose there's a bug in a drawing program that you're working on. To reproduce the bug, you open the solution
in Visual Studio and press F5 to start debugging.
When you draw a line and choose Undo my last stroke, nothing happens until you draw the next line.
So you start investigating by searching for the Undo method. You find it in the PaintCanvas class.

Start mapping the code


Now start mapping the undo method and its relationships. From the code editor, you add the undo method and
the fields that it references to a new code map. When you create a new map, it might take some time to index the
code. This helps later operations run faster.
TIP
The green highlighting shows the last items that were added to the map. The green arrow shows your cursor's position in
the code. Arrows between items represent different relationships. You can get more info about items on the map by
moving the mouse over them and examining their tooltips.

Navigate and examine code from the map


To see the code definition for each field, double-click the field on the map or select the field and press F12. The
green arrow moves between items on the map. Your cursor in the code editor also moves automatically.
TIP
You can also move the green arrow on the map by moving your cursor in the code editor.

Understand relationships between pieces of code


Now you want to know which other code interacts with the history and paintObjects fields. You can add all the
methods that reference these fields to the map. You can do this from the map or from the code editor.
NOTE
If you add items from a project that's shared across multiple apps, like Windows Phone or Windows Store, then those items
always appear with the currently active app project on the map. So, if you change the context to another app project, then
the context on the map also changes for any newly added items from the shared project. Operations that you perform with
an item on the map apply only to those items that share the same context.

Change the layout to rearrange the flow of relationships and make the map easier to read. You can also move
items around the map by dragging them.

TIP
By default, Incremental Layout is turned on. This rearranges the map as little as possible when you add new items. To
rearrange the entire map every time you add new items, turn off Incremental Layout.
Let's examine these methods. On the map, double-click the PaintCanvas method, or select this method and press
F12. You learn that this method creates history and paintObjects as empty lists.

Now repeat the same steps to examine the clear method definition. You learn that clear performs some tasks
with paintObjects and history . It then calls the Repaint method.
Now examine the addPaintObject method definition. It also performs some tasks with history and
paintObjects . It also calls Repaint .

Find the problem by examining the map


It seems that all the methods that modify history and paintObjects call Repaint . Yet the undo method doesn't
call Repaint , even though undo modifies the same fields. So you think you can fix this problem by calling
Repaint from undo .
If you didn't have a map to show you this missing call, it might have been harder to find this problem, especially
with more complex code.

Share your discovery and next steps


Before you or someone else fixes this bug, you can make notes on the map about the problem and how to fix it.

For example, you can add comments to the map and flag items using colors.
If you have Microsoft Outlook installed, you can email the map to others. You can also export the map as an
image or another format.

Fix the problem and show what you did


To fix this bug, you add the call for Repaint to undo .

To confirm your fix, you restart your debugging session and try to reproduce the bug. Now choosing Undo my
last stroke works as you expect and confirms you made the correct fix.
You can update the map to show the fix you made.

Your map now shows a link between undo and Repaint.


NOTE
When you update the map, you might see a message that says the code index used to create your map was updated. This
means someone changed the code, which causes your map to not match the current code. This doesn't stop you from
updating the map, but you might have to recreate the map to confirm that it matches the code.

Now you're done with your investigation. You successfully found and fixed the problem by mapping the code.
You also have a map that helps you navigate around the code, remember what you learned, and shows the steps
you took to fix the problem.

See Also
Map methods on the call stack while debugging
Visualize code
Map methods on the call stack while debugging in
Visual Studio
10/18/2017 4 min to read Edit Online

Create a code map to visually trace the call stack while you're debugging. You can make notes on the map to track
what the code is doing so you can focus on finding bugs.

You'll need:
Visual Studio Enterprise
Code that you can debug, such as Visual C# .NET, Visual Basic .NET, C++, JavaScript, or X++
See:
Video: Debug visually with Code Map debugger integration (Channel 9)
Map the call stack
Make notes about the code
Update the map with the next call stack
Add related code to the map
Find bugs using the map
Q&A
For details of the commands and actions you can use when working with code maps, see Browse and
rearrange code maps.
Map the call stack
1. Start debugging. (Keyboard: F5)
2. After your app enters break mode or you step into a function, choose Code Map. (Keyboard: Ctrl + Shift +
`)

The current call stack appears in orange on a new code map:

The map will update automatically while you continue debugging. See Update the map with the next call
stack.

Make notes about the code


Add comments to track what's happening in the code. To add a new line in a comment, press Shift + Return.
Update the map with the next call stack
Run your app to the next breakpoint or step into a function. The map adds a new call stack.

Add related code to the map


Now you've got a map - what next? If you're working with Visual C# .NET or Visual Basic .NET, add items, such as
fields, properties, and other methods, to track what's happening in the code.
Double-click a method to see its code definition, or use the shortcut menu for the method. (Keyboard: Select the
method on the map and press F12)
Add the items that you want to track on the map.

NOTE
By default, adding items to the map also adds the parent group nodes such as the class, namespace, and assembly. While this
is useful, you can keep the map simple by turning off this feature using the Include Parents button on the map toolbar, or
by pressing CTRL when you add items.

Here you can easily see which methods use the same fields. The most recently added items appear in green.
Continue building the map to see more code.
Find bugs using the map
Visualizing your code can help you find bugs faster. For example, suppose you're investigating a bug in a drawing
program. When you draw a line and try to undo it, nothing happens until you draw another line.
So you set breakpoints in the clear , undo , and Repaint methods, start debugging, and build a map like this one:
You notice that all the user gestures on the map call Repaint , except for undo . This might explain why undo
doesn't work immediately.
After you fix the bug and continue running the program, the map adds the new call from undo to Repaint :

Q&A
Not all calls appear on the map. Why?
By default, only your own code appears on the map. To see external code, turn it on in the Call Stack
window:
or turn off Enable Just My Code in the Visual Studio debugging options:

Does changing the map affect the code?


Changing the map doesn't affect the code in any way. Feel free to rename, move, or remove anything on the
map.
What does this message mean: "The diagram may be based on an older version of the code"?
The code might have changed after you last updated the map. For example, a call on the map might not exist
in code anymore. Close the message, then try rebuilding the solution before updating the map again.
How do I control the map's layout?
Open the Layout menu on the map toolbar:
Change the default layout.
To stop rearranging the map automatically, turn off Automatically Layout when Debugging.
To rearrange the map as little as possible when you add items, turn off Incremental Layout.
Can I share the map with others?
You can export the map, send it to others if you have Microsoft Outlook, or save it to your solution so you
can check it into Team Foundation version control.

How do I stop the map from adding new call stacks automatically?
Choose on the map toolbar. To manually add the current call stack to the map, press Ctrl + Shift + `.
The map will continue highlighting existing call stacks on the map while you're debugging.
What do the item icons and arrows mean?
To get more info about an item, move the mouse pointer over it and look at the item's tooltip. You can also
look at the Legend to learn what each icon means.

See:
Map the call stack
Make notes about the code
Update the map with the next call stack
Add related code to the map
Find bugs using the map

See Also
Map dependencies across your solutions
Use code maps to debug your applications
Find potential problems using code map analyzers
Browse and rearrange code maps
Find potential problems using code map analyzers
10/18/2017 1 min to read Edit Online

Run analyzers on code maps to help you identify code that might be overly complex or that might need
improvement. For example, you can use these analyzers:

TO FIND CODE THAT HAS EXAMINE THESE AREAS TO SEE WHETHER

Loops or circular dependencies You can simplify them and consider whether you can break
these cycles.

Too many dependencies They are performing too many functions or to determine the
impact of changing these areas. A well-formed code map will
show a minimal number of dependencies. To make code
easier to maintain, change, test, and reuse, consider whether
you can refactor these areas so that they are more clearly
defined, or whether you can merge code that performs
similar functions.

No dependencies They are necessary or whether you should remove this code.

Analyze code maps


1. On the map toolbar, choose Layout, Analyzers, and then analyzer that you want to run:

ANALYZER TO IDENTIFY NODES THAT

Circular References Analyzer Have circular dependencies on each other. Note: Circular
dependencies that are in the Generics group are not
shown on the map when you expand the group.

Find Hubs Analyzer Are in the top 25% of highly-connected nodes

To hide all other nodes on the map

- Open the shortcut menu for the map, choose


Advanced, Select, Hide Unselected.
The map hides the unselected nodes, and the analyzer
identifies new nodes as hubs.

Unreferenced Nodes Analyzer Do not have references from any other nodes. Caution:
Verify each of these cases before assuming that the code
is not used. Certain dependencies such as XAML
dependencies and run-time dependencies cannot be
found statically in the code.

Code map analyzers will continue to run after you apply them. If you change the map, any applied
analyzers will automatically reprocess the updated map. To stop running an analyzer, on the map toolbar,
choose Layout, Analyzers. Turn off the selected analyzer.
TIP
If you have a very large map, running an analyzer might cause an out of memory exception. If this occurs, edit the map to
reduce its scope or generate a smaller one, and then run the analyzer.

See Also
Map dependencies across your solutions
Use code maps to debug your applications
Map methods on the call stack while debugging
Browse and rearrange code maps
10/18/2017 23 min to read Edit Online

Rearrange items on code maps to make them easier to read and improve their performance.
You can customize code maps without affecting the underlying code in a solution. This is useful when you want
to focus on key code elements or communicate ideas about the code. For example, to highlight interesting areas,
you can select code elements on the map and filter them, change the style of code elements and links, hide or
delete code elements, and organize code elements using properties, categories, or groups.
Requirements
To create code maps, you must have Visual Studio Enterprise.
You can view code maps and make limited edits to code maps in Visual Studio Professional.

Get started working with code maps


Create a code map (see Map dependencies across your solutions for more details). If you don't want to wait for
the map to finish generating, click the Cancel link at any time to stop the generation process. However, you will
not see the details of all dependencies and links if you do this.
After you generate the map, get started with these tips for reviewing your code:
Look at the natural dependency clusters in the code. On the map toolbar, choose Layout, Quick Clusters
. See Change the map layout.

Organize the map into smaller areas by grouping related nodes. Collapse those groups to see only the
intergroup dependencies, which appear automatically. See Group nodes.
Use filters to simplify the map and focus on the types of nodes or links you are interested in. See Filter
nodes and links.
Maximize the performance of large maps. See Map dependencies across your solutions for more
information.For example, turn on Skip Build on the map toolbar so that Visual Studio doesn't rebuild
your solution when you update items on the map.

Change the map layout


TO PERFORM THESE STEPS

Arrange the dependency flow for the entire map in a specific On the map toolbar, choose Layout, and then:
direction. This can help you see architectural layers in the
code. - Top to Bottom
- Bottom to Top
- Left to Right
- Right to Left

See natural dependency clusters in the code with the most On the map toolbar, choose Layout, and then Quick
dependent nodes at the center of the clusters and the least Clusters .
dependent nodes at the outside of those clusters.

Select one or more nodes on the map. Click on a node to select it. To select or deselect more than
one node, hold CTRL while clicking.

Keyboard: press TAB or use the arrow keys to move the


dotted focus rectangle to a node and press SPACE to select
it. Press CTRL + SPACE to multi-select or deselect nodes.

Move specific nodes around on the map. Drag nodes to move them. To move other nodes and links
out of the way as you drag nodes, press and hold the SHIFT
key.

Keyboard: hold CTRL and press the arrow keys.

Change the layout inside a group independently of the other Select a node and open the shortcut menu. Choose Layout
nodes and groups on the map. and select a layout style.

- or -

Select a node and expand it to show the child nodes. Click


the node title to show group pop-up toolbar, and open the
Change the layout style of the group list. Select one
of the tree layouts, Quick Clusters, or List View (which
arranges the group's contents into a list).

See Group nodes for more details.

Undo an action in the map. Press CTRL + Z or use the Visual Studio Undo command.

Browse the map


TO PERFORM THESE STEPS

Scan the map. Drag the map in any direction using the mouse.

- or -

Hold SHIFT and rotate the mouse wheel to scroll


horizontally. Hold SHIFT + CTRL and rotate the mouse
wheel to scroll horizontally.
TO PERFORM THESE STEPS

Zoom in or out of the map. Rotate the mouse wheel.

- or -

Use the Zoom drop-down list on the code map toolbar.

- or -

Use the keyboard shortcuts. To zoom in, press CTRL +


SHIFT + . (period). To zoom out, press CTRL + SHIFT + ,
(comma).

Zoom in on a specific area using the mouse. Hold the right mouse button while drawing a rectangle
around that area you are interested in.

Resize and fit the map in its window. Choose Zoom to Fit from the Zoom list on the code map
toolbar.

- or -

Click the icon on the code map toolbar.


Zoom to fit
Keyboard: press CTRL + 0 (zero).

Find a node on the map by its name. Tip: This works only for 1. Choose the icon on the code map toolbar
items on the map. To find items in your solution but not on Find
the map, find them in Solution Explorer, and then drag (Keyboard: press CTRL + F) to show the search box in the
them to the map. (Drag your selection, or on the Solution upper right corner of the map.
Explorer toolbar, click Show on Code Map). 2. Type the item name and press Return or click the
"magnifier" icon. The first item that matches your search
appears selected on the map.
3. To customize your search, open the drop-down list and
choose a search option. The options are Find Next, Find
Previous, and Select All. Then click the corresponding
button next to the search textbox.

Alternatively, use the keyboard: press F3 to select the next


matching node or SHIFT + F3 to select the previous
matching node.
4. Select any one of the options that specify how search
terms are handled by clicking the icons below the search
textbox.

The options are, from left to right, case sensitive matching,


match whole words only, use .NET regular expression syntax,
automatically expand groups to show matches to enclosed
items. Important: You can use the search box to find
matches in collapsed groups only if those groups were
expanded previously. To find these matches and expand their
parent groups automatically, choose this option under the
search box.

Select all unselected nodes. Open the shortcut menu for the selected nodes. Choose
Select, Invert Selection.
TO PERFORM THESE STEPS

Select additional nodes that link to the selected ones. Open the shortcut menu for the selected nodes. Choose
Select and one of these:

- To select additional nodes that link directly to the selected


node, choose Incoming Dependencies.
- To select additional nodes that link directly from the
selected node, choose Outgoing Dependencies.
- To select additional nodes that link directly to and from the
selected node, choose Both.
- To select all nodes that link to and from the selected node,
choose Connected Subgraph.
- To select all children of the selected node, choose Children.

Filter nodes and links


TO PERFORM THESE STEPS

Show or hide the Filters pane. Choose the Filters button on the code map toolbar. The
Filters pane is displayed as a tabbed page in the Solution
Explorer window by default.

Filter the types of nodes that are shown on the map. Set or clear the checkboxes in the Code Elements list in the
Filters pane.

Filter the types of links that are shown on the map. Set or clear the checkboxes in the Relationships list in the
Filters pane.

Show or hide Test project nodes on the map. Set or clear the Test Assets checkbox in the Miscellaneous
list in the Filters pane.

The icons shown in the Legend panel of the map reflect the settings you make in the list. To show or hide the
Legend panel, click the Legend button on the code map toolbar.

Examine nodes and links


Code maps show these kinds of links:
An individual link represents a single relationship between two nodes.
A cross-group link represents a relationship between two nodes in different groups.
An aggregate link represents all the relationships that point in the same direction between two groups.

TIP
By default, the map shows cross-group links only for selected nodes. To change this behavior to show or hide aggregated
links between groups, click Layout on the code map toolbar and choose Advanced, then Show All Cross-Group Links
or Hide All Cross-Group Links. See Hide or show nodes and links for more details.

TO PERFORM THESE STEPS


TO PERFORM THESE STEPS

See more information about a node or a link. Move the mouse pointer on top of the node or link until a
tooltip appears.

The tooltip for an aggregated link lists the individual


dependencies that it represents.

- or -

Open the shortcut menu for the node or the link. Choose
Edit, Properties.

Show or hide the contents of a group. - To expand a group, open the shortcut menu for the node
and choose Group, Expand.
- or -
Move the mouse pointer on top of the node until the
chevron (down arrow) button appears. Click this button to
expand the group. Keyboard: to expand or collapse the
selected group, press the PLUS key (+) or the MINUS key (-).
- To collapse a group, open the shortcut menu for the node
and choose Group, Collapse.
- or -
Move the mouse pointer on top of a group until the chevron
(up arrow) button appears. Click this button to collapse the
group.
- To expand all groups, press CTRL + A to select all the
nodes. Open the shortcut menu for the map and choose
Group, Expand. Note: This command is not available if
expanding all groups generates an unusable map or memory
issues. It is recommended that you expand the map only to
the level of detail that you care about.
- To collapse all groups, open the shortcut menu for a node
or for the map. Choose Group, Collapse All.
TO PERFORM THESE STEPS

See the code definition for a namespace, type, or member. Open the shortcut menu for the node and choose Go To
Definition.

-or-

Double-click the node. For expanded groups, double-click the


header on the group.

-or-

Select the node and press F12.

For example:

- For a namespace containing one class, the code file for the
class opens to show the definition of that class. In other
cases, the Find Symbol Results window shows a list of code
files. Note: When you perform this task on a Visual Basic
.NET namespace, the code file behind the namespace does
not open. This issue also occurs when you perform this task
on a group of selected nodes that include a Visual Basic .NET
namespace. To work around this issue, browse manually to
the code file behind the namespace, or omit the node for the
namespace from your selection.
- For a class or a partial class, the code file for that class
opens to show the class definition.
- For a method, the code file for the parent class opens to
show the method definition.

Examine dependencies and items that participate in an Select the links you're interested in and open the shortcut
aggregate link. menu for your selection. Choose Show Contributing Links
or Show Contributing Links on New Code Map.

Visual Studio expands the groups at both ends of the link


and shows only those items and dependencies that
participate in the link. Note: When you examine
dependencies between items in partial groups, you might see
this behavior:
Links to items that don't participate in your
examination disappear from the map, even though
those links still exist.
Suppose you examine a link to an item in a partial
group, and then later examine a different link to the
same item. During your second examination, the
target partial group shows only items from your first
examination. Links and target items that didn't
participate in your first examination but participate in
your second examination don't appear.
To see missing items from a group, choose Refetch Children
(which indicates that not all members of a group appear
on the map). You can also try undoing your actions
(Keyboard: press CTRL+Z) and examine the dependencies on
a new map.
TO PERFORM THESE STEPS

Examine dependencies across multiple nodes in different Expand the groups so you can see all their children. Select all
groups. the nodes that interest you, including their children. The map
shows the cross-group links between the selected nodes.

To select all nodes in a group, press and hold SHIFT and the
left mouse button while you draw a rectangle around that
group. To select all nodes on a map, press CTRL+A. Tip: To
show cross-group links at all times, choose Layout on the
map toolbar, Advanced, Show All Cross-Group Links.

See the items that a node or link references. Open the shortcut menu for the node and choose Find All
References. Note: This applies only when the Reference
attribute is set for the node or link in the map's .dgml file. To
add references to items from nodes or links, see Customize
code maps by editing the DGML files.

Hide or show nodes and links


Hiding nodes keeps them from participating in layout algorithms. By default, cross-group links are hidden.
Cross-group links are individual links that connect nodes across groups. When groups are collapsed, the map
aggregates all cross-group links into single links between groups. When you expand a group and select nodes
inside the group, cross-group links appear and show the dependencies in that group.
Cau t i on

Before you share a map that was created in Visual Studio Enterprise with those who use Visual Studio
Professional, make sure to unhide any nodes or cross-group links that you want others to see. Otherwise, those
users won't be able to unhide those items.
To hide or show nodes
TO PERFORM THESE STEPS

Hide selected nodes. 1. Select nodes you want to hide.


2. Open the shortcut menu for the selected nodes or for the
map. Choose Select, Hide Selected.

Hide unselected nodes. 1. Select nodes you want to remain visible.


2. Open the shortcut menu for the selected nodes or for the
map. Choose Select, Hide Unselected.

Show hidden nodes. - To show all hidden nodes inside a group, first make sure
the group is expanded. Open the shortcut menu and choose
Select, Unhide Children.
- or -
Click the Unhide Children icon in the upper left corner of
the group (this is visible only when there are hidden child
nodes).
- To show all hidden nodes, open the shortcut menu for the
map or a node and choose Select, Unhide All.

To hide or show links


ON THE MAP TOOLBAR, CHOOSE LAYOUT, ADVANCED, AND THEN
TO CHOOSE
ON THE MAP TOOLBAR, CHOOSE LAYOUT, ADVANCED, AND THEN
TO CHOOSE

Show cross-group links at all times. Show All Cross-Group Links. This hides aggregated links
between groups.

Hide cross-group links at all times. Hide All Cross-Group Links

Show only cross-group links for selected nodes. Show Cross-Group Links On Selected Nodes

Hide all links. Hide All Links. To show links again, choose one of the
options listed above.

Group nodes
TO PERFORM THESE STEPS

Show container nodes as group nodes or leaf nodes. To show container nodes as leaf nodes: select the nodes,
open the shortcut menu for your selection, and choose
Group, Convert To Leaf.

To show container nodes as group nodes: select the nodes,


open the shortcut menu for your selection, and choose
Group, Convert To Group.

Change the layout inside a group. Select the group, open the shortcut menu, choose Layout,
and select the layout style you want.

- or -

1. Select the group and make sure it is expanded.


2. Click the group header again and the group toolbar
appears.

3. Open the Change the layout style of the group list


and choose the layout style you want.

List View rearranges the group's members into list. Graph


Default resets the group layout to the map default layout.
For other options, see Change the map layout.

Add a node to a group. Drag the node onto the group.

While you drag the node, Visual Studio displays an indicator


to show that you are moving the node.

You can also drag nodes out of a group.

Add a node to a non-group node. Drag the node onto the target node. You can convert any
target node into a group by adding nodes to it.
TO PERFORM THESE STEPS

Group selected nodes. 1. Select the nodes that you want to group. A pop-up
toolbar appears above the last node you select.

2. On the toolbar, choose the fourth icon Group the


selected nodes (if the node is expanded it will have five
instead of four icons). Type the name for the new group and
press Return.
- or -
Select the nodes that you want to group and open the
shortcut menu for your selection. Choose Group, Add
Parent Group, type the name for the new group, and press
Return.

You can rename a group. Open the shortcut menu for the
group and choose Edit, Properties to open the Visual
Studio Properties window. In the Label property, rename the
group as required.

Remove groups. Select the group or groups that you want to remove. Open
the shortcut menu for your selection and choose Group,
Remove Group.

Remove nodes from their parent group. Select the nodes that you want to move. Open the shortcut
menu for your selection and choose Group, Remove From
Parent. This removes nodes up to their grandparent, or to
outside the group if they have no grandparent group.

- or -

Select the nodes and drag them out of the group.

Add, remove, or rename nodes, links, and comments


You can display more or fewer items on a map in order to drill down or to simplify the map. You can also
rename items, and add comments to items.
Cau t i on

Before you share a map that was created using Visual Studio Enterprise with those who use Visual Professional,
make sure any code elements you want others to see are visible on the map. Otherwise, those users won't be
able to retrieve deleted code elements.
Add a node for a code element
TO PERFORM THESE STEPS

Add a new generic node at the current mouse pointer 1. Move the mouse pointer to the place on the map where
location. you want to put the new code element and press Insert.
- or -
Open the shortcut menu for the map and choose Edit, Add,
Generic Node.
2. Type the name for the new node and press Return.
TO PERFORM THESE STEPS

Add a specific type of code element node at the current 1. Move the mouse pointer to the place on the map where
mouse pointer location. you want to put the new code element and open the
shortcut menu for the map.
2. Choose Edit, Add, and select the type of node you want.
3. Type the name for the new node and press Return.

Add a generic or a specific type of code element node to a 1. Select the group node and open the shortcut menu.
group. 2. Choose Edit, Add, and select the type of node you want.
3. Type the name for the new node and press Return.

Add a new node of the same type, and linked from, an 1. Select the code element. A pop-up toolbar appears above
existing node. it.

2. On the toolbar, choose the second icon Create a node


with the same category as this node and add a new link
to it.
3. Choose a place on the map to put the new code element
and click the left mouse button.
4. Type the name for the new node and press Return.

Add a new generic node that is linked from an existing code 1. Using the keyboard, press Tab until the code element to
element that has focus. link from has the focus (dotted rectangle).
2. Press Alt+Insert.
3. Type the name for the new node and press Return.

Add a new generic node that links to an existing code 1. Using the keyboard, press Tab until the code element to
element that has focus. link to has the focus (dotted rectangle).
2. Press Alt+Shift+Insert.
3. Type the name for the new node and press Return.

TO ADD CODE ELEMENTS FOR PERFORM THESE STEPS


TO ADD CODE ELEMENTS FOR PERFORM THESE STEPS

Code elements in the solution. 1. Find the code element in Solution Explorer. Use the
Solution Explorer search box or browse the solution. Tip:
To find code elements that have dependencies on a type or a
member, open the shortcut menu for the type or the
member in Solution Explorer. Choose the relationship that
interests you. Solution Explorer shows only those code
elements with the specified dependencies.
2. Drag the code elements that interest you to the map
surface. You can also drag code elements from Class View or
Object Browser.
- or -
In Solution Explorer, select the code elements that you
want to map. Then, on the Solution Explorer toolbar, click
Show on Code Map.

By default, the parent container hierarchy for the new code


elements is shown on the map. Use the Include Parents
button on the code map toolbar to change this behavior.
When turned off, only the code element itself is added to the
map. To reverse this behavior for just one drag and drop
action, press and hold the CTRL key while you drag the code
elements to the map.

Visual Studio adds code elements for the top-level code


elements in your selection. To see if a code element contains
other code elements, move the mouse pointer on top of the
code element so that the chevron (down arrow) appears.
Choose the chevron to expand the code element. To expand
all code elements, press CTRL+A to select all elements, open
the shortcut menu for the map, and choose Group, Expand.
This command is not available if expanding all groups would
produce an unusable map or cause shortage of memory
issues.

Code elements related to code elements on the map. Click the Show Related button on the code map toolbar
and choose the type of related items you are interested in.

- or -

Open the shortcut menu for the code element. Choose one
of the Show ... items on the menu depending on the kind of
relationship that interests you. For example, you can see
items that the current item references, items that reference
the current item, base and derived types for classes, method
callers, and the containing classes, namespaces, and
assemblies.

For more details, see this topic.

Compiled .NET assemblies (.dll or .exe) or binaries. Drag the assemblies or binaries from outside Visual Studio to
a map.

You can drag from Windows Explorer or File Explorer only if


you are running it and Visual Studio at the same User Access
Control (UAC) permissions level. For example, if UAC is
turned on and you are running Visual Studio as
Administrator, Windows Explorer or File Explorer will block
the dragging operation.

A d d a l i n k b e t w e e n e x i st i n g c o d e e l e m e n t s

1. Select the source code element. A toolbar appears above the code element.
2. On the toolbar, choose the first icon, Create new link from this node to which ever node that you
click on next.
3. Select the target code element. A link appears between the two code elements.
- or -
4. Select the source code element on the map.
5. If you have a mouse installed, move the mouse pointer outside the bounds of the map.
6. Open the code element's shortcut menu and choose Edit, Add, Generic Link.
7. Tab to and select the target code element for the link.
8. Press RETURN.
A d d a c o m m e n t t o a n e x i st i n g n o d e o n t h e m a p

1. Select the code element. A toolbar appears above it.

2. On the toolbar, choose the third icon, Create a new comment node with a new link to the selected
node.
- or -
Open the shortcut menu for the code element and choose Edit, New Comment.
3. Type your comments. To type on a new line, press SHIFT + RETURN.
A d d a c o m m e n t t o t h e m a p i t se l f

1. Open the shortcut menu for the map and choose Edit, New Comment.
2. Type your comments. To type on a new line, press SHIFT + RETURN.
Ren am e a c o de el em en t o r l i n k

1. Select the code element or the link you want to rename.


2. Press F2, or open the shortcut menu and choose Edit, Rename.
3. When the edit box appears in the map, rename the code element or the link.
- or -
4. Open the shortcut menu and choose Edit, Properties.
5. Edit the Label property in the Visual Studio Properties window.
R e m o v e a c o d e e l e m e n t o r l i n k fr o m t h e m a p

1. Select the code element or link and press the Delete key.
- or -
Open the shortcut menu for the code element or link and choose Edit, Remove.
2. If the element or link is part of a group, the Refetch Children button appears inside the group. Click
this to retrieve missing elements and links.
You can remove code elements and links from a map without affecting the underlying code. When you
delete them, their definitions are removed from the DGML (.dgml) file.
Maps created by editing the DGML, by adding undefined code elements, or by using some earlier versions
of Visual Studio, do not support this capability.
F l a g a c o d e e l e m e n t fo r fo l l o w - u p

1. Select the code element or link you want to flag for follow-up.
2. Open the shortcut menu and choose Edit, Flag for Follow Up.
By default, the code element gains a red background. Consider adding a comment to it with the
appropriate follow-up information.
Change the background color of the element or clear the follow-up flag by choosing Edit, Other Flag
Colors.

Change the style of a code element or link


You can change the icons on code elements and the colors of code elements and links using predefined icons
and colors. For example, you can choose a color to highlight code elements and links that have a certain category
or property. This lets you identify and focus on specific areas of the map. You can specify custom icons and
colors by editing the map's .dgml file; see Customize code maps by editing the DGML files.
To apply a predefined color or icon to code elements or links with a certain category or property
1. On the map toolbar, choose Legend.
2. In the Legend box, see if the code element category or property already appears in the list.
3. If the list does not include the category or property, choose + in the Legend box, then choose Node
Property, Node Category, Link Property, or Link Category. Then choose the property or category. The
category or property now appears in the Legend box.

NOTE
To create and assign a category or a property to a code element, you can edit the map's .dgml file; see Customize
code maps by editing the DGML files.

4. In the Legend box, click the icon next to the category or property you added or you want to change.
5. Use the following table to select the style that you want to change:

TO CHANGE THE CHOOSE

Background color Background

Outline color Stroke

Text color (a letter "f" is displayed to show the result) Foreground

Icon Icons

The Color Set Picker or Icon Set Picker dialog box appears for you to select a color or icon.
6. In the Color Set Picker or Icon Set Picker dialog box, do one of the following:

TO APPLY A PERFORM THESE STEPS

Set of colors or icons Open the Select color (or icon) set list. Select a set of
colors or icons.
TO APPLY A PERFORM THESE STEPS

Specific color or icon Open the category or property value list. Select a color or
icon.

NOTE
You can rearrange, delete, or temporarily inactivate styles in the Legend box. See Edit the Legend box.

Edit the Legend box


You can rearrange, delete, or temporarily inactivate styles in the Legend box:
1. Open the shortcut menu for a style in the Legend box.
2. Perform one of the following tasks:

TO CHOOSE

Deactivate the code element Disable

Delete the code element Delete

Move the style up Move Up

Move the code element down Move Down

Copy styles from one map to another


1. Make sure the Legend box appears on the source map. If it is not visible, on the map toolbar, click
Legend.
2. Open the shortcut menu for the Legend box. Choose Copy Legend.
3. Paste the legend onto the target map.

Merge code maps


You can merge maps by copying and pasting code elements between maps. If the code element identifiers
match, then pasting code elements functions like a merge operation. To make this task easier, put all the
assemblies or binaries that you want to visualize in the same folder so that the full path of each assembly or
binary is the same for each map that you want to merge.
Alternatively, you can drag those assemblies or binaries to the same map from that folder.

See Also
Map dependencies across your solutions
Use code maps to debug your applications
Find potential problems using code map analyzers
Customize code maps by editing the DGML files
Directed Graph Markup Language (DGML) reference
Customize code maps by editing the DGML files
10/18/2017 12 min to read Edit Online

To customize a code map, you can edit a map's Directed Graph Markup Language (.dgml) file. For example, you
can edit elements to specify custom styles, assign properties and categories to code elements and links, or link
documents or URLs to code elements or to links. For more information about DGML elements, see Directed
Graph Markup Language (DGML) reference.
Edit the code map's .dgml file in a text or XML editor. If the map is part of your Visual Studio solution, select it in
Solution Explorer, open the shortcut menu, and choose Open With, XML (Text) Editor.

NOTE
To create code maps, you must have Visual Studio Enterprise. When you edit a code map in Visual Studio, it cleans up any
unused DGML elements and attributes by deleting them when you save the .dgml file. It also creates code elements
automatically when you manually add new links. When you save the .dgml file, any attributes that you added to an
element might rearrange themselves in alphabetical order.

Group code elements


You can add new groups or convert existing nodes into a group.
1. Open the .dgml file in a text or XML editor.
2. To convert a code element to a group, find the <Node/> element for that code element.
- or -
To add a new group, find the <Nodes> section. Add a new <Node/> element.
3. In the <Node/> element, add a Group attribute to specify whether the group appears expanded or
collapsed. For example:

<Nodes>
<Node Id="MyFirstGroup" Group="Expanded" />
<Node Id="MySecondGroup" Group="Collapsed" />
</Nodes>

4. In the <Links> section, make sure that a <Link/> element that has the following attributes exist for each
relationship between a group code element and its child code elements:
A Source attribute that specifies the group code element
A Target attribute that specifies the child code element
A Category attribute that specifies a Contains relationship between the group code element and
its child code element
For example:
<Links>
<Link Category="Contains" Source="MyFirstNewGroup" Target="FirstGroupChildOne" />
<Link Category ="Contains" Source="MyFirstNewGroup" Target="FirstGroupChildTwo" />
<Link Category ="Contains" Source="MySecondNewGroup" Target="SecondGroupChildOne" />
<Link Category="Contains" Source="MySecondNewGroup" Target="SecondGroupChildTwo" />
</Links>

For more information about the Category attribute, see Assign categories to code elements and links.

Change the style of the map


You can change the background color and border color of the map by editing the map's .dgml file. To change the
style of code elements and links, see Change the style of code elements and links.
1. Open the .dgml file in a text or XML editor.
2. In the <DirectedGraph> element, add any of the following attributes to change its style:
Background color

Background="ColorNameOrHexadecimalValue"

Border color

Stroke="StrokeValue"

For example:

<DirectedGraph Background="Green" xmlns="http://schemas.microsoft.com/vs/2009/dgml" >


...
...
</DirectedGraph>

Change the style of code elements and links


You can apply custom styles to the following code elements:
Single code elements and links
Groups of code elements and links
Groups of code elements and links based on certain conditions

TIP
If you have repeating styles across many code elements or links, you might consider applying a category to those code
elements or links, and then applying a style to that category. For more information, see Assign Categories to Code
elements and Links and Assign Properties to Code elements and Links.

To a p p l y a c u st o m st y l e t o a si n g l e c o d e e l e m e n t

1. Open the .dgml file in a text or XML editor.


2. Find the code element's <Node/> element. Add any of these attributes to customize its style:
Background color
Background="ColorNameOrHexadecimalValue"

Outline

Stroke="ColorNameOrHexadecimalValue"

Outline thickness

StrokeThickness="StrokeValue"

Text color

Foreground="ColorNameOrHexadecimalValue"

Icon

Icon="IconFilePathLocation"

Text size

FontSize="FontSizeValue"

Text type

FontFamily="FontFamilyName"

Text weight

FontWeight="FontWeightValue"

Text style

FontStyle="FontStyleName"

For example, you can specify Italic as the text style.


Texture

Style="Glass"

or -

Style="Plain"

Shape
To replace the shape with an icon, set the Shape property to None and set the Icon property to the path
with the icon file.
Shape="ShapeFilePathLocation"

For example:

<Nodes>
<Node Id="MyNode" Background="#FF008000" Stroke="#FF000000"
Foreground="#FFFFFFFF" Icon="...\Icons\Globe.png"/>
</Nodes>

To a p p l y a c u st o m st y l e t o a si n g l e l i n k

1. Open the .dgml file in a text or XML editor.


2. Find the <Link/> element that contains both the names of the source code element and target code
element.
3. In the <Link/> element, add any of the following attributes to customize its style:
Outline and arrowhead color

Stroke="ColorNameOrHexadecimalValue"

Outline thickness

StrokeThickness="StrokeValue"

Outline style

StrokeDashArray="StrokeArrayValues"

For example:

<Links>
<Link Source="MyFirstNode" Target="MySecondNode" Background="Green" Stroke="#FF000000"
StrokeDashArray="2,2"/>
</Links>

To a p p l y c u st o m st y l e s t o a g r o u p o f c o d e e l e m e n t s o r l i n k s

1. Open the .dgml file in a text or XML editor.


2. If a <Styles></Styles> element does not exist, add one under the <DirectedGraph></DirectedGraph>
element after the <Links></Links> element.
3. In the <Styles></Styles> element, under the <Style/> element and specify the following attributes:
TargetType="Node | Link | Graph"

GroupLabel=" NameInLegendBox "

ValueLabel=" NameInStylePickerBox "

To apply a custom style to all target types, do not use a condition.


To a p p l y a c o n d i t i o n a l st y l e t o g r o u p s o f c o d e e l e m e n t s o r l i n k s

1. Open the .dgml file in a text or XML editor.


2. In the <Style/> element, add a <Condition/> element that contains an Expression attribute to specify an
expression that returns a Boolean value.
For example:

<Condition Expression="MyCategory"/>

or -

<Condition Expression="MyCategory > 100"/>

or -

<Condition Expression="HasCategory('MyCategory')"/>

This expression uses the following Backus-Naur Form (BNF) syntax:


::= | | "("")" | | |
::=
::= "!" | "+" | "-"
::= "<" | "<=" | "=" | ">=" | ">" | "!=" | "or" | "and" | "+" | "*" | "/" | "-"
::= | "."
::= |
::= "(" ")"
::= Identifier
::= | "," |
::= [^. ]*
::= single or double-quoted string literal
::= string of digits with optional decimal point
You can specify multiple <Condition/> elements, which must all be true to apply the style.
3. On the next line after the <Condition/> element, add one or multiple <Setter/> elements to specify a
Property attribute and a fixed Value attribute or a computed Expression attribute to apply to the map,
code elements, or links that meet the condition.
For example:

<Setter Property="BackGround" Value="Green"/>

As a simple complete example, the following condition specifies that a code element appears green or red
based on whether its Passed category is set to True or False :
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="MyFirstNode" Passed="True" />
<Node Id="MySecondNode" Passed="False" />
</Nodes>
<Links>
</Links>
<Styles>
<Style TargetType="Node" GroupLabel="Passed" ValueLabel="True">
<Condition Expression="Passed='True'"/>
<Setter Property="Background" Value="Green"/>
</Style>
<Style TargetType="Node" GroupLabel="Passed" ValueLabel="False">
<Condition Expression="Passed='False'"/>
<Setter Property="Background" Value="Red"/>
</Style>
</Styles>
</DirectedGraph>

The following table includes some example conditions that you can use:
Set the font size as a function of the number of lines of code, which also changes the size of the code element.
This example uses a single conditional expression to set multiple properties, FontSize and FontFamily .

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Class1" LinesOfCode ="200" />
<Node Id="Class2" LinesOfCode ="1000" />
<Node Id="Class3" LinesOfCode ="20" />
</Nodes>
<Properties>
<Property Id="LinesOfCode" Label="LinesOfCode" Description="LinesOfCode" DataType="System.Int32" />
</Properties>
<Styles>
<Style TargetType="Node" GroupLabel="LinesOfCode" ValueLabel="Function">
<Condition Expression="LinesOfCode > 0" />
<Setter Property="FontSize" Expression="Math.Max(9,Math.Sqrt(LinesOfCode))" />
<Setter Property="FontFamily" Value="Papyrus" />
</Style>
</Styles>
</DirectedGraph>

Set the background color of a code element based on the Coverage property. The styles are evaluated in the
order that they appear, similar to if-else statements.
In this example:
1. If Coverage is > 80, then set the Background property to green.
2. Else if Coverage is > 50, then set the Background property to a shade of orange based on the value of the
Coverage property.
3. Else set the Background property to a shade of red based on the value of the Coverage property.
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Class1" Coverage="58" />
<Node Id="Class2" Coverage="95" />
<Node Id="Class3" Coverage="32" />
</Nodes>
<Properties>
<Property Id="Coverage" Label="Coverage" Description="Code coverage as a percentage of blocks"
DataType="Double" />
</Properties>
<Styles>
<Style TargetType="Node" GroupLabel="Coverage" ValueLabel="Good">
<Condition Expression="Coverage > 80" />
<Setter Property="Background" Value="Green" />
</Style>
<Style TargetType="Node" GroupLabel="Coverage" ValueLabel="OK">
<Condition Expression="Coverage > 50" />
<Setter Property="Background" Expression="Color.FromRgb(180 * Math.Max(1, (80 - Coverage) / 30), 180,
0)" />
</Style>
<Style TargetType="Node" GroupLabel="Coverage" ValueLabel="Bad">
<Setter Property="Background" Expression="Color.FromRgb(180, 180 * Coverage / 50, 0)" />
</Style>
</Styles>
</DirectedGraph>

Set the Shape property to None so that the icon replaces the shape. Use the Icon property to specify the
location of the icon.

<DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Automation" Category="Test" Label="Automation" />
<Node Id="C# Provider" Category="Provider" Label="C# Provider" />
</Nodes>
<Categories>
<Category Id="Provider" Icon="...\Icons\Module.png" Shape="None" />
<Category Id="Test" Icon="...\Icons\Page.png" Shape="None" />
</Categories>
<Properties>
<Property Id="Icon" DataType="System.String" />
<Property Id="Label" Label="Label" Description="Displayable label of an Annotatable object"
DataType="System.String" />
<Property Id="Shape" DataType="System.String" />
</Properties>
<Styles>
<Style TargetType="Node" GroupLabel="Group" ValueLabel="Has category">
<Condition Expression="HasCategory('Group')" />
<Setter Property="Background" Value="#80008080" />
</Style>
<Style TargetType="Node">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Styles>
</DirectedGraph>

Assign properties to code elements and links


You can organize code elements and links by assigning properties to them. For example, you can select code
elements that have specific properties so that you can group them, change their style, or hide them.
To assign a property to a code element
1. Open the .dgml file in a text or XML editor.
2. Find the <Node/> element for that code element. Specify the name of the property and its value. For
example:

<Nodes>
<Node Id="MyNode" MyPropertyName="PropertyValue" />
</Nodes>

3. Add a <Property/> element to the <Properties> section to specify attributes such as its visible name and
data type:

<Properties>
<Property Id="MyPropertyName" Label="My Property" DataType="System.DataType"/>
</Properties>

To assign a property to a link


1. Open the .dgml file in a text or XML editor.
2. Find the <Link/> element that contains both the names of the source code element and target code
element.
3. In the <Node/> element, specify the name of the property and its value. For example:

<Links>
<Link Source="MyFirstNode" Target="MySecondNode" MyPropertyName="PropertyValue" />
</Links>

4. Add a <Property/> element to the <Properties> section to specify attributes such as its visible name and
data type:

<Properties>
<Property Id="MyPropertyName" Label="My Property Name" DataType="System.DataType"/>
</Properties>

Assign categories to code elements and links


The following sections demonstrate how you can organize code elements by assigning categories to them, and
how you can create hierarchical categories that help you organize code elements and add attributes to child
categories by using inheritance.
To assign a category to a code element
Open the .dgml file in a text or XML editor.
Find the <Node/> element for the code element that you want.
In the <Node/> element, add a Category attribute to specify the name of the category. For example:

<Nodes>
<Node Id="MyNode" Category="MyCategory" />
</Nodes>

Add a <Category/> element to the <Categories> section so that you can use the Label attribute to
specify the display text for that category:
<Categories>
<Category Id="MyCategory" Label="My Category" />
</Categories>

To assign a category to a link


1. Open the .dgml file in a text or XML editor.
2. Find the <Link/> element that contains both the names of the source code element and target code
element.
3. In the <Link/> element, add a Category attribute to specify the name of the category. For example:

<Links>
<Link Source="MyFirstNode" Target="MySecondNode" Category="MyCategory"
</Links>

4. Add a <Category/> element to the <Categories> section so that you can use the Label attribute to
specify the display text for that category:

<Categories>
<Category Id="MyCategory" Label="My Category" />
</Categories>

To create hierarchical categories


1. Open the .dgml file in a text or XML editor.
2. Add a <Category/> element for the parent category, and then add the BasedOn attribute to the child
category's <Category/> element.
For example:

<Nodes>
<Node Id="MyFirstNode" Label="My First Node" Category= "MyCategory" />
<Node Id="MySecondNode" Label="My Second Node" />
</Nodes>
<Links>
<Link Source="MyFirstNode" Target="MySecondNode" />
</Links>
<Categories>
<Category Id="MyCategory" Label="My Category" BasedOn="MyParentCategory"/>
<Category Id="MyParentCategory" Label="My Parent Category" Background="Green"/>
</Categories>

In this example, the background of MyFirstNode is green because its Category attribute inherits the
Background attribute of MyParentCategory .

Link documents or URLs to code elements and links


You can link documents or URLs to code elements or to links by editing the map's .dgml file and adding a
Reference attribute to the <Node/> element for a code element or the <Link/> element for a link. You can then
open and view that content from the code element or link. The Reference attribute specifies the path of that
content. This can be a path relative to the location of the .dgml file or an absolute path.
Cau t i on

If you use relative paths, and the .dgml file is moved to a different location, then those paths will no longer
resolve. When you try to open and view the linked content, an error stating that the content cannot be viewed
will occur.
For example, you might want to link the following code elements:
To describe the changes to a class, you might link the URL of a work code element, document, or another
.dgml file to the code element for a class.
You might link a dependency diagram to a group code element that represents a layer in the software's
logical architecture.
To show more information about a component that exposes an interface, you might link a component
diagram to the code element for that interface.
Link a code element to a Team Foundation Server work item or bug, or some other information that is
related to the code element.
To link a document or URL to a code element
1. Open the .dgml file in a text or XML editor.
2. Find the <Node/> element for the code element that you want.
3. Perform one of the tasks in the following table:
A single code element
In the <Node/> or <Link/> element, add a Reference attribute to specify the location of the code
element.

NOTE
You can have only one Reference attribute per element.

For example:

<Nodes>
<Node Id="MyNode" Reference="MyDocument.txt" />
</Nodes>
<Properties>
<Property Id="Reference" Label="My Document" DataType="System.String" IsReference="True" />
</Properties>

Multiple code elements


a. In the <Node/> or <Link/> element, add a new attribute to specify the location of each reference.
b. In the <Properties> section:
a. Add a <Property/> element for each new type of reference.
b. Set the Id attribute to the name of the new reference attribute.
c. Add the IsReference attribute and set it to True to make the reference appear on the code
element's Go To Reference shortcut menu.
d. Use the Label attribute to specify the display text on the code element's Go To Reference
shortcut menu.
For example:
<Nodes>
<Node Id="MyNode" SequenceDiagram="MySequenceDiagram.sequencediagram"
ActiveBugs="MyActiveBugs.wiq"/>
</Nodes>
<Properties>
<Property Id="SequenceDiagram" Label="My Sequence Diagram" DataType="System.String"
IsReference="True" />
<Property Id="ActiveBugs" Label="Active Bugs" DataType="System.String" IsReference="True" />
</Properties>

On the map, the name of the code element appears underlined. When you open the shortcut menu for the
code element or the link, you will see a Go To Reference shortcut menu that contains the linked code
elements for you to choose.
4. Use the ReferenceTemplate attribute to specify a common string, such as a URL, that is used by multiple
references instead of repeating that string in the reference.
The ReferenceTemplate attribute specifies a placeholder for the value of the reference. In the following
example, the {0} placeholder in the ReferenceTemplate attribute will be replaced by the values of the
MyFirstReference and MySecondReference attributes in the <Node/> element to produce a full path:

<Nodes>
<Node Id="MyNode" MyFirstReference="MyFirstDocument" MySecondReference="MySecondDocument"/>
<Node Id="MySecondNode" MyFirstReference="AnotherFirstDocument"
MySecondReference="AnotherSecondDocument"/>
</Nodes>
<Properties>
<Property Id="MyFirstReference" Label="My First Document" DataType="System.String"
IsReference="True" ReferenceTemplate="http://www.Fabrikam.com/FirstDocuments/{0}.asp"/>
<Property Id="MySecondReference" Label="My Second Document" DataType="System.String"
IsReference="True" ReferenceTemplate=" http://www.Fabrikam.com/SecondDocuments/{0}.asp"/>
</Properties>

5. To view the referenced code element or code elements from the map, open the shortcut menu for the
code element or the link. Choose Go To Reference and then the code element.

See Also
Map dependencies across your solutions
Use code maps to debug your applications
Find potential problems using code map analyzers
Browse and rearrange code maps
Directed Graph Markup Language (DGML) reference
Directed Graph Markup Language (DGML) reference
10/18/2017 7 min to read Edit Online

Directed Graph Markup Language (DGML) describes information used for visualization and to perform complexity
analysis, and is the format used to persist code maps in Visual Studio. It uses simple XML to describe both cyclical
and acyclic directed graphs. A directed graph is a set of nodes that are connected by links, or edges. Nodes and
links can be used represent network structures, such as elements in a software project.
Note that some versions of Visual Studio support only a subset of DGML capabilities, see Version support for
architecture and modeling tools.

NOTE
When you edit a .dgml file, IntelliSense helps you identify attributes that are available for each element and their values. To
specify color in an attribute, use names for common colors, such as "Blue", or ARGB hexadecimal values, such as "#ffa0b1c3".
DGML uses a small subset of Windows Presentation Foundation (WPF) color definition formats. For more information, see
Colors Class.

DGML syntax
The following table describes kinds of elements that are used in DGML:
<DirectedGraph></DirectedGraph>

This element is the root element of code map (.dgml) document. All other DGML elements appear within
the scope of this element.
The following list describes optional attributes that you can include:
Background - The color of the map background
BackgroundImage - The location of an image file to use as the map background.
GraphDirection - When the map is set to tree layout ( Sugiyama ), arrange the nodes so that most of the
links flow in the specified direction: TopToBottom , BottomToTop , LeftToRight , or RightToLeft . See Change
the map layout.
Layout - Set the map to the following layouts: None , Sugiyama (tree layout), ForceDirected (quick
clusters), or DependencyMatrix . See Change the map layout.
NeighborhoodDistance - When the map is set to tree layout or quick clusters layout, show only those nodes
that are a specified number (1-7) of links away from selected nodes. See Change the map layout.
Example:
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph Title="DrivingTest" Background="Blue" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
...
</Nodes>
<Links>
...
</Links>
<Categories>
...
</Categories>
<Properties>
...
</Properties>
</DirectedGraph>

<Nodes></Nodes>

This optional element contains a list of <Node/> elements, which define nodes on the map. For more
information, see the <Node/> element.

NOTE
When you reference an undefined node in a <Link/> element, the map creates a <Node/> element automatically.

Example:

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node ... />
</Nodes>
<Links>
<Link ... />
</Links>
</DirectedGraph>

<Node/>

This element defines a single node. It appears within the <Nodes><Nodes/> element list.
This element must include the following attributes:
Id - The unique name of the node and the default value of the Label attribute, if no separate Label
attribute is specified. This name must match the Source or Target attribute of the link that references it.
The following list describes some of the optional attributes that you can include:
Label - The display name of the node.
Style attributes. See Customize code maps by editing the DGML files.
Category - The name of a category that identifies elements that share this attribute. For more information,
see the <Category/> element.
Property - The name of a property that identifies elements that have the same property value. For more
information, see the <Property/> element.
Group - If the node contains other nodes, set this attribute to Expanded or Collapsed to show or hide its
contents. There must be a <Link/> element that includes the Category="Contains" attribute and specifies
the parent node as the source node and the child node as the target node. See Group code elements.
Visibility - Set this attribute to Visible , Hidden , or Collapsed . Uses System.Windows.Visibility . See
Hide or show nodes and links.
Reference - Set this attribute to link to a document or URL. See Link documents or URLs to code elements
and links.
Example:

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Driver" Label="Student" Category="Person" />
<Node Id="Passenger" Label="Instructor" Category="Person" />
<Node Id="Car" Label="Car" Category="Automobile" />
<Node Id="Truck" Label="Truck" Category="Automobile" />
</Nodes>
<Links>
<Link ... />
</Links>
<Categories>
<Category Id="Person" Background="Orange" />
<Category Id="Automobile" Background="Yellow"/>
</Categories>
</DirectedGraph>

<Links></Links>

This element contains the list of <Link> elements, which define links between nodes. For more information,
see the <Link/> element.
Example:

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Links>
<Link ... />
</Links>
</DirectedGraph>

<Link/>

This element defines a single link that connects a source node to a target node. It appears within the
<Links></Links> element list.

NOTE
If this element references an undefined node, the map document automatically creates a node that has the specified
attributes, if any.

This element must include the following attributes:


Source - The source node of the link
Target - The target node of the link
The following list describes some of the optional attributes that you can include:
Label - The display name of the link
Style attributes. See Customize code maps by editing the DGML files.
Category - The name of a category that identifies elements that share this attribute. For more information,
see the <Category/> element.
Property - The name of a property that identifies elements that have the same property value. For more
information, see the <Property/> element.
Example:

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Driver" Label="Student" Category="Person" />
<Node Id="Passenger" Label="Instructor" Category="Person" />
<Node Id="Car" Label="Car" Category="Automobile" />
<Node Id="Truck" Label="Truck" Category="Automobile" />
</Nodes>
<Links>
<Category Id="Person" Background="Orange" />
<Category Id="Automobile" Background="Yellow"/>
<Link Source="Driver" Target="Car" Label="Passed" Stroke="Black" Background="Green"
Category="PassedTest" />
<Link Source="Driver" Target="Truck" Label="Failed" Stroke="Black" Background="Red"
Category="PassedTest" />
</Links>
</DirectedGraph>

<Categories></Categories>

This element contains the list of <Category/> elements. For more information, see the <Category/>
element.
Example:

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Categories>
<Category ... />
</Categories>
</DirectedGraph>

<Category/>

This element defines a Category attribute, which is used to identify elements that share this attribute. A
Category attribute can be used to organize map elements, provide for shared attributes through
inheritance, or define additional metadata.
This element must include the following attributes:
Id - The unique name of the category and the default value of the Label attribute, if no separate Label
attribute is specified.
The following list describes some of the optional attributes that you can include:
Label - A reader-friendly name for the category.
BasedOn - The parent category from which the <Category/> of the current element inherits.
In the example for this element, the FailedTest category inherits its Stroke attribute from the PassedTest
category. See "To create hierarchical categories" in Customize code maps by editing the DGML files.
Categories also provide some basic template behavior that controls the appearance of nodes and links
when they are displayed on a map. See Customize code maps by editing the DGML files.
Example:

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Driver" Label="Driver" Category="Person" />
<Node Id="Car" Label="Car" Category="Automobile" />
<Node Id="Truck" Label="Truck" Category="Automobile" />
<Node Id="Passenger" Category="Person" />
</Nodes>
<Links>
<Link Source="Driver" Target="Car" Label="Passed" Category="PassedTest" />
<Link Source="Driver" Target="Truck" Label="Failed" Category="FailedTest" />
</Links>
<Categories>
<Category Id="Person" Background="Orange" />
<Category Id="Automobile" Background="Yellow"/>
<Category Id="PassedTest" Label="Passed" Stroke="Black" Background="Green" />
<Category Id="FailedTest" Label="Failed" BasedOn="PassedTest" Background="Red" />
</Categories>
</DirectedGraph>

<Properties></Properties>

This element contains the list of <Property/> elements. For more information, see the <Property/>
element.
Example:

<?xml version="1.0" encoding="utf-8"?>


<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Properties>
<Property ... />
</Properties>
</DirectedGraph>

<Property/>

This element defines a Property attribute that you can use to assign a value to any DGML element or
attribute, including categories and other properties.
This element must include the following attributes:
Id - The unique name of the property and the default value of the Label attribute, if no separate
Label attribute is specified.

DataType - The type of data stored by the property


If you want the property to appear in the Properties window, use the Label property to specify the
property's display name.
See Assign categories to code elements and links.
Example:
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph Title="DrivingTest" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Driver" Label="Driver" Category="Person" DrivingAge="18"/>
<Node Id="Car" Label="Car" Category="Automobile" />
<Node Id="Truck" Label="Truck" Category="Automobile" />
<Node Id="Passenger" Category="Person" />
</Nodes>
<Links>
<Link Source="Driver" Target="Car" Label="Passed" Category="PassedTest" />
<Link Source="Driver" Target="Truck" Label="Failed" Category="FailedTest" />
</Links>
<Categories>
<Category Id="Person" Background="Orange" />
<Category Id="Automobile" Background="Yellow"/>
<Category Id="PassedTest" Label="Passed" Stroke="Black" Background="Green" />
<Category Id="FailedTest" Label="Failed" BasedOn="PassedTest" Background="Red" />
</Categories>
<Properties>
<Property Id="DrivingAge" Label="Driving Age" DataType="System.Int32" />
</Properties>
</DirectedGraph>

Aliases for commonly-used paths


Replacing commonly-used paths with aliases helps reduce the size of the .dgml file and the time required to load
or save the file. To create an alias, add a <Paths></Paths> section at the end of the .dgml file. In this section, add a
<Path/> element to define an alias for the path:

<Paths>
<Path Id="MyPathAlias" Value="C:\...\..." />
</Paths>

To reference the alias from an element in the .dgml file, enclose the Id of the <Path/> element with a dollar sign
($) and parentheses (()):

<Nodes>
<Node Id="MyNode" Reference="$(MyPathAlias)MyDocument.txt" />
</Nodes>
<Properties>
<Property Id="Reference" Label="My Document" DataType="System.String" IsReference="True" />
</Properties>

See Also
Map dependencies across your solutions
Use code maps to debug your applications
Find potential problems using code map analyzers
Create dependency diagrams from your code
10/18/2017 9 min to read Edit Online

To visualize your software system's high-level, logical architecture, create a dependency diagram in Visual
Studio. To make sure that your code stays consistent with this design, validate your code with a dependency
diagram. You can create dependency diagrams for Visual C# .NET and Visual Basic .NET projects. To see which
versions of Visual Studio support this feature, see Version support for architecture and modeling tools

A dependency diagram lets you organize Visual Studio solution items into logical, abstract groups called layers.
You can use layers to describe major tasks that these artifacts perform or the system's major components. Each
layer can contain other layers that describe more detailed tasks. You can also specify the intended or existing
dependencies between layers. These dependencies, which are represented as arrows, show which layers can use
or currently use the functionality represented by other layers. To maintain architectural control of the code, show
the intended dependencies on the diagram and then validate the code against the diagram.
Video: Validate your architecture dependencies in real time

Create a dependency diagram


Before you create a dependency diagram, make sure your solution has a modeling project.

IMPORTANT
Don't add, drag, or copy an existing dependency diagram from a modeling project to another modeling project or to
another place in the solution. This preserves the references from the original diagram, even if you change the diagram.
This also prevents layer validation from working correctly and might cause other issues, such as missing elements or other
errors when you try to open the diagram.
Instead, add a new dependency diagram to the modeling project. Copy the elements from the source diagram to the new
diagram. Save both the modeling project and the new dependency diagram.

To add a new dependency diagram to a modeling project


1. On the Architecture menu, choose New Dependency Diagram.
2. Under Templates, choose dependency diagram.
3. Name the diagram.
4. In Add to Modeling Project, browse to and select an existing modeling project in your solution.
-or-
Choose Create a new modeling project to add a new modeling project to the solution.

NOTE
The dependency diagram must exist inside a modeling project. However, you can link it to items anywhere in the
solution.

5. Make sure to save both the modeling project and the dependency diagram.

Drag and drop, or copy and paste, from a Code Map


1. Generate a Code Map for the solution using the Architecture menu.
2. Consider applying a Code Map filter to remove solution folders and "Test Assets" if you only want to
enforce dependencies in product code.
3. On the generated Code Map, remove the "External" node, or expand it to show external assemblies,
depending on whether you want to enforce namespace dependencies, and delete non-required
assemblies from the Code Map.
4. Create a new Dependency Diagram for the solution using the Architecture menu
5. Select all the nodes on the Code Map (use Ctrl + A, or use the rubber band selection by pressing the Shift
key before you click, drag, and release.
6. Drag and drop, or a copy and paste, the selected elements to the new Dependency Validation diagram.
7. This shows the current app architecture. Decide what you want the architecture to be and modify the
dependency diagram accordingly.

Create layers from artifacts


You can create layers from Visual Studio solution items, such as projects, code files, namespaces, classes, and
methods. This automatically creates links between layers and items, including them in the layer validation
process.
You can also link layers to items that don't support validation, such as Word documents or PowerPoint
presentations, so that you can associate a layer with specifications or plans. You can also link layers to files in
projects that are shared across multiple apps, but the validation process won't include those layers, which appear
with generic names such as "Layer 1" and "Layer 2".
To see if a linked item supports validation, open Layer Explorer and examine the Supports Validation
property of the item. See Managing links to artifacts.

TO FOLLOW THESE STEPS

Create a layer for a single artifact 1. Drag the item onto the dependency diagram from
these sources:

Solution Explorer

For example, you can drag files or projects.


Code maps

See Map dependencies across your solutions


and Use code maps to debug your
applications.
Class View or Object Browser

A layer appears on the diagram and is linked to the


artifact.
2. Rename the layer to reflect the responsibilities of the
associated code or artifacts.
Important: Dragging binary files to the dependency diagram
does not automatically add their references to modeling
project. You must manually add the binary files that you
want to validate to the modeling project. To add binary
files to the modeling project
1. In Solution Explorer, open the shortcut menu for
the modeling project, and then choose Add Existing
Item.
2. In the Add Existing Item dialog box, browse to the
binary files, select them, and then choose OK. The
binary files appear in the modeling project.
3. In Solution Explorer, choose a binary file that you
added, and then press F4 to open the Properties
window.
4. On each binary file, set the Build Action property to
Validate.

Create a single layer for all selected artifacts Drag all the artifacts to the dependency diagram at the same
time.

A layer appears on the diagram and is linked to all of the


artifacts.
TO FOLLOW THESE STEPS

Create a layer for each selected artifact Press and hold the SHIFT key while you drag all of the
artifacts to the dependency diagram at the same time. Note:
If you use the SHIFT key to select a range of items, release
the key after you select the artifacts. Press and hold it again
when you drag the artifacts to the diagram.

A layer for each artifact appears on the diagram and is linked


to each artifact.

Add an artifact to a layer Drag the artifact to the layer.

Create a new unlinked layer In the Toolbox, expand the Dependency Diagram section,
and then drag a Layer to the dependency diagram.

To add multiple layers, double-click the tool. When you are


finished, choose the Pointer tool or press the ESC key.

- or -

Open the shortcut menu for the dependency diagram,


choose Add, and then choose Layer.

Create nested layers Drag an existing layer onto another layer.

- or -

Open the shortcut menu for a layer, choose Add, and then
choose Layer.

Create a new layer that contains two or more existing layers Select the layers, open the shortcut menu for your selection,
and then choose Group.

Change the color of a layer Set its Color property to the color that you want.

Specify that artifacts associated with a layer must not belong Type the namespaces in the layer's Forbidden Namespaces
to the specified namespaces property. Use a semicolon (;) to separate the namespaces.

Specify that artifacts associated with a layer cannot depend Type the namespaces in the layer's Forbidden Namespace
on the specified namespaces Dependencies property. Use a semicolon (;) to separate the
namespaces.

Specify that artifacts associated with a layer must belong to Type the namespace in the layer's Required Namespaces
one of the specified namespaces property. Use a semicolon (;) to separate the namespaces.

The number on a layer indicates the number of artifacts that are linked to the layer. However, when reading this
number, remember the following:
If a layer links to an artifact that contains other artifacts, but the layer does not link directly to the other
artifacts, then the number includes only the linked artifact. However, the other artifacts are included for
analysis during layer validation.
For example, if a layer is linked to a single namespace, then the number of linked artifacts is 1, even if the
namespace contains classes. If the layer also has links to each class in the namespace, then the number
will include the linked classes.
If a layer contains other layers that are linked to artifacts, then the container layer is also linked to those
artifacts, even though the number on the container layer does not include those artifacts.
Manage links between layers and artifacts
1. On the dependency diagram, open the shortcut menu for the layer, and then choose View Links.
Layer Explorer shows the artifact links for the selected layer.
2. Use the following tasks to manage these links:

TO IN LAYER EXPLORER

Delete the link between the layer and an artifact Open the shortcut menu for the artifact link, and then
choose Delete.

Move the link from one layer to another Drag the artifact link to an existing layer on the diagram.

- or -

1. Open the shortcut menu for the artifact link, and then
choose Cut.
2. On the dependency diagram, open the shortcut menu for
the layer, and then choose Paste.

Copy the link from one layer to another 1. Open the shortcut menu for the artifact link, and then
choose Copy.
2. On the dependency diagram, open the shortcut menu for
the layer, and then choose Paste.

Create a new layer from an existing artifact link Drag the artifact link to a blank area on the diagram.

Verify that a linked artifact supports validation against the Look at the Supports Validation column for the artifact link.
dependency diagram.

Reverse-engineer existing dependencies


A dependency exists wherever an artifact that is associated with one layer has a reference to an artifact that is
associated with another layer. For example, a class in one layer declares a variable that has a class in another
layer. You can reverse-engineer existing dependencies for artifacts that are linked to layers on the diagram.

NOTE
Dependencies cannot be reverse-engineered for certain kinds of artifacts. For example, no dependencies will be reverse-
engineered from or to a layer that is linked to a text file. To see which artifacts have dependencies that you can reverse-
engineer, open the shortcut menu for one or multiple layers, and then choose View Links. In Layer Explorer, examine
the Supports Validation column. Dependencies will not be reverse-engineered for artifacts for which this column shows
False.

Select one or multiple layers, open the shortcut menu for a selected layer, and then choose Generate
Dependencies.
Typically, you will see some dependencies that should not exist. You can edit these dependencies to align
them with the intended design.

Edit layers and dependencies to show the intended design


To describe the changes that you plan to make to your system or the intended architecture, edit the dependency
diagram:

TO PERFORM THESE STEPS

Change or restrict the direction of a dependency Set its Direction property.

Create new dependencies Use the Dependency and Bidirectional Dependency tools.

To draw multiple dependencies, double-click the tool. When


you are finished, choose the Pointer tool or press the ESC
key.

Specify that artifacts associated with a layer cannot depend Type the namespaces in the layer's Forbidden Namespace
on the specified namespaces Dependencies property. Use a semicolon (;) to separate the
namespaces.

Specify that artifacts associated with a layer must not belong Type the namespaces in the layer's Forbidden Namespaces
to the specified namespaces property. Use a semicolon (;) to separate the namespaces.

Specify that artifacts associated with a layer must belong to Type the namespace in the layer's Required Namespaces
one of the specified namespaces property. Use a semicolon (;) to separate the namespaces.

Change how elements appear on the diagram


You can change the size, shape, color, and position of layers or the color of dependencies by editing their
properties.

Discover patterns and dependencies on a code map


While creating dependency diagrams, you might also create code maps. These diagrams can help you discover
patterns and dependencies while you explore the code. Use Solution Explorer, Class View, or Object Browser to
explore assemblies, namespaces, and classes - which often correspond well to existing layers. For more
information about code maps, see:
Map dependencies across your solutions
Use code maps to debug your applications
Find potential problems using code map analyzers

See Also
Video: Validate your architecture dependencies in real time
Dependency Diagrams: Reference
Dependency Diagrams: Guidelines
Validate code with dependency diagrams
Visualize code
Create models for your app
10/18/2017 1 min to read Edit Online

Modeling diagrams help you understand, clarify, and communicate ideas about your code and the user
requirements that your software system must support.
To see which versions of Visual Studio support each type of diagram, see Version support for architecture and
modeling tools.
To visualize the architecture of a system or existing code, create the following diagrams:

DIAGRAM SHOWS

Dependency Diagrams: Guidelines High-level architecture of the system

Dependency Diagrams: Reference

Code maps Dependencies and other relationships in existing code

Map dependencies across your solutions

Find potential problems using code map analyzers

Code-generated class diagrams Types and their relationships in .NET code

Working with Class Diagrams (Class Designer)

Related Tasks
TOPIC TASK

Visualize code Create code maps and dependency diagrams to better


understand unfamiliar code.

Model user requirements Use models to clarify and communicate the users' needs.

Model your app's architecture Use models to describe the overall structure and behavior of
your system and to make sure that it meets the users' needs.

Validate your system during development Make sure that your software stays consistent with your
users' needs and the overall architecture of your system.

Use models in your development process Use models to help you understand and change your system
during its development.
Use models in Agile development

Structure your modeling solution Organize models in a large or medium project.

External Resources
CATEGORY LINKS

Forums - Visual Studio Visualization & Modeling Tools


- Visual Studio Visualization & Modeling SDK (DSL Tools)
Dependency Diagrams: Reference
10/18/2017 3 min to read Edit Online

In Visual Studio, you can use a dependency diagram to visualize the high-level, logical architecture of your
system. A dependency diagram organizes the physical artifacts in your system into logical, abstract groups called
layers. These layers describe major tasks that the artifacts perform or the major components of your system.
Each layer can also contain nested layers that describe more detailed tasks.
To see which versions of Visual Studio support this feature, see Version support for architecture and modeling
tools.
You can specify the intended or existing dependencies between layers. These dependencies, which are
represented as arrows, indicate which layers can use or currently use the functionality represented by other
layers. By organizing your system into layers that describe distinct roles and functions, a dependency diagram
can help make it easier for you to understand, reuse, and maintain your code.
Use a dependency diagram to help you perform the following tasks:
Communicate the existing or intended logical architecture of your system.
Discover conflicts between your existing code and the intended architecture.
Visualize the impact of changes on the intended architecture when you refactor, update, or evolve your
system.
Reinforce the intended architecture during the development and maintenance of your code by including
validation with your check-in and build operations.
This topic describes the elements that you can use on a dependency diagram. For more detailed
information about how to create and draw dependency diagrams, see Dependency Diagrams: Guidelines.
For more information about layering patterns, visit the Patterns & Practices site.

Reading dependency diagrams

The following table describes the elements that you can use on a dependency diagram.

SHAPE ELEMENT DESCRIPTION


SHAPE ELEMENT DESCRIPTION

1 Layer A logical group of physical artifacts in


your system. These artifacts can be
namespaces, projects, classes, methods,
and so on.

To see the artifacts that are linked to a


layer, open the shortcut menu for the
layer, and then choose View Links to
open Layer Explorer.

For more information, see Layer


Explorer.

- Forbidden Namespace
Dependencies - Specifies that artifacts
associated with this layer cannot
depend on the specified namespaces.
- Forbidden Namespaces - Specifies
that artifacts associated with this layer
must not belong to the specified
namespaces.
- Required Namespaces - Specifies
that artifacts associated with this layer
must belong to one of the specified
namespaces.

2 Dependency Indicates that one layer can use the


functionality in another layer, but not
vice versa.

- Direction - Specifies the direction of


the dependency.

3 Bidirectional Dependency Indicates that one layer can use the


functionality in another layer, and vice
versa.

- Direction - Specifies the direction of


the dependency.

4 Comment Use to add general notes to the


diagram or elements on the diagram.

5 Comment Link Use to link comments to elements on


the diagram.

Layer Explorer
You can link each layer to artifacts in your solution, such as projects, classes, namespaces, project files, and other
parts of your software. The number on a layer shows the number of artifacts that are linked to the layer.
However, when reading the number of artifacts on a layer, remember the following:
If a layer links to an artifact that contains other artifacts, but the layer does not link directly to the other
artifacts, then the number includes only the linked artifact. However, the other artifacts are included for
analysis during layer validation.
For example, if a layer is linked to a single namespace, then the number of linked artifacts is 1, even if the
namespace contains classes. If the layer also has links to each class in the namespace, then the number
will include the linked classes.
If a layer contains other layers that are linked to artifacts, then the container layer is also linked to those
artifacts, even though the number on the container layer does not include those artifacts.
For more information about linking layers and artifacts, see:
Dependency diagrams: Guidelines
Create dependency diagrams from your code
To examine the linked artifacts
On the dependency diagram, open the shortcut menu for one or more layers, and then choose View
Links.
Layer Explorer opens and shows the artifacts that are linked to the selected layers. Layer Explorer has a
column that shows each of the properties of the artifact links.

NOTE
If you cannot see all of these properties, expand the Layer Explorer window.

COLUMN IN LAYER EXPLORER DESCRIPTION

Categories The kind of artifact, such as a class, namespace, source


file, and so on

Layer The layer that links to the artifact

Supports Validation If True, then the layer validation process can verify that
the project conforms to dependencies to or from this
element.

If False, then the link does not participate in the layer


validation process.

For more information, see Dependency Diagrams:


Guidelines.

Identifier The reference to the linked artifact

See Also
Create models for your app
Dependency Diagrams: Guidelines
11/7/2017 10 min to read Edit Online

Describe your app's architecture at a high level by creating dependency diagrams in Visual Studio. Make sure
that your code stays consistent with this design by validating your code with a dependency diagram. You can
also include layer validation in your build process. See Channel 9 Video: Design and validate your architecture
using dependency diagrams.
To see which versions of Visual Studio support this feature, see Version support for architecture and modeling
tools.

What is a dependency diagram?


Like a traditional architecture diagram, a dependency diagram identifies the major components or functional
units of the design and their interdependencies. Each node on the diagram, called a layer, represents a logical
group of namespaces, projects, or other artifacts. You can draw the dependencies that should exist in your
design. Unlike a traditional architecture diagram, you can verify that the actual dependencies in the source code
conform to the intended dependencies that you have specified. By making validation part of a regular build on
Team Foundation Server, you can ensure that the program code continues to adhere to the system's
architecture through future changes. See Dependency Diagrams: Reference.

How to design or update your app with dependency diagrams


The following steps provide an overview of how to use dependency diagrams within the development process.
Later sections in this topic describe more detail about each step. If you are developing a new design, omit the
steps that refer to existing code.

NOTE
These steps appear in approximate order. You will probably want to overlap the tasks, reorder them to suit your own
situation, and revisit them at the start of each iteration in your project.

1. Create a dependency diagram for the whole application, or for a layer within it.
2. Define layers to represent primary functional areas or components of your application. Name these
layers according to their function, for example, "Presentation" or "Services". If you have a Visual Studio
solution, you can associate each layer with a collection of artifacts, such as projects, namespaces, files,
and so on.
3. Discover the existing dependencies between layers.
4. Edit the layers and dependencies to show the updated design that you want the code to reflect.
5. Design new areas of your application by creating layers to represent the principal architectural blocks or
components and defining dependencies to show how each layer uses the others.
6. Edit the layout and appearance of the diagram to help you discuss it with colleagues.
7. Validate the code against the dependency diagram to highlight the conflicts between the code and the
architecture you require.
8. Update the code to conform to your new architecture. Iteratively develop and refactor code until the
validation shows no conflicts.
9. Include layer validation in the build process to ensure that the code continues to adhere to your design.

Create a dependency diagram


A dependency diagram must be created inside a modeling project. You can add a new dependency diagram to
an existing modeling project, create a new modeling project for the dependency diagram, or copy an existing
dependency diagram within the same modeling project.

IMPORTANT
Do not add, drag, or copy an existing dependency diagram from a modeling project to another modeling project or to
another location in the solution. A dependency diagram that is copied in this way will have the same references as the
original diagram, even if you modify the diagram. This will prevent layer validation from working correctly and might cause
other issues, such as missing elements or other errors when trying to open the diagram.

See Create dependency diagrams from your code.

Define layers to represent functional areas or components


Layers represent logical groups of artifacts, such as projects, code files, namespaces, classes, and methods. You
can create layers from artifacts from Visual C# .NET and Visual Basic .NET projects, or you can attach
specifications or plans to a layer by linking documents, such as Word files or PowerPoint presentations. Each
layer appears as a rectangle on the diagram and shows the number of artifacts that are linked to it. A layer can
contain nested layers that describe more specific tasks.
As a general guideline, name layers according to their function, for example, "Presentation" or "Services". If the
artifacts are closely interdependent, place them in the same layer. If the artifacts can be updated separately or
used in separate applications, place them in different layers. To learn about layering patterns, visit the Patterns &
Practices site at http://go.microsoft.com/fwlink/?LinkId=145794.

TIP
There are certain types of artifacts that you can link to layers but that do not support validation against the dependency
diagram. To see whether the artifact supports validation, open Layer Explorer to examine the Supports Validation
property of the artifact link. See Discover existing dependencies between layers.

When updating an unfamiliar application, you might also create code maps. These diagrams can help you
discover patterns and dependencies while you explore the code. Use Solution Explorer to explore namespaces
and classes, which often correspond well to existing layers. Assign these code artifacts to layers by dragging
them from Solution Explorer to dependency diagrams. You can then use dependency diagrams to help you
update the code and keep it consistent with your design.
See:
Create dependency diagrams from your code
Use code maps to debug your applications
Map dependencies across your solutions

Discover existing dependencies between layers


A dependency exists wherever an artifact that is associated with one layer has a reference to an artifact that is
associated with another layer. For example, a class in one layer declares a variable that has a class in another
layer. You can discover existing dependencies by reverse-engineering them.

NOTE
Dependencies cannot be reverse-engineered for certain kinds of artifacts. For example, no dependencies will be reverse-
engineered from or to a layer that is linked to a text file. To see which artifacts have dependencies that you can reverse-
engineer, right-click one or multiple layers, and then click View Links. In Layer Explorer, examine the Supports
Validation column. Dependencies will not be reverse-engineered for artifacts for which this column shows False.

To reverse-engineer existing dependencies between layers


Select one layer or multiple layers, right-click a selected layer, and then click Generate Dependencies.
Typically, you will see some dependencies that should not exist. You can edit these dependencies to align
them with the intended design.

Edit layers and dependencies to show the intended design


To describe the changes that you plan to make to your system or the intended architecture, use the following
steps to edit the dependency diagram. You might also consider making some refactoring changes to improve
the structure of the code before extending it. See Improving the structure of the code.

TO PERFORM THESE STEPS

Delete a dependency that should not exist Click the dependency, and then press DELETE.

Change or restrict the direction of a dependency Set its Direction property.

Create new dependencies Use the Dependency and Bidirectional Dependency


tools.

To draw multiple dependencies, double-click the tool. When


you are finished, click the Pointer tool or press the ESC key.

Specify that artifacts associated with a layer cannot depend Type the namespaces in the layer's Forbidden Namespace
on the specified namespaces Dependencies property. Use a semicolon (;) to separate the
namespaces.

Specify that artifacts associated with a layer must not belong Type the namespaces in the layer's Forbidden
to the specified namespaces Namespaces property. Use a semicolon (;) to separate the
namespaces.

Specify that artifacts associated with a layer must belong to Type the namespace in the layer's Required Namespaces
one of the specified namespaces property. Use a semicolon (;) to separate the namespaces.

Improving the structure of the code


Refactoring changes are improvements that do not affect the behavior of the application, but help make the
code easier to change and extend in the future. Well-structured code has a design that is easy to abstract to a
dependency diagram.
For example, if you create a layer for each namespace in the code and then reverse-engineer the dependencies,
there should be a minimal set of one-way dependencies between the layers. If you create a more detailed
diagram using classes or methods as your layers, then the result should also have the same characteristics.
If this is not the case, the code will be more difficult to change throughout its life and will be less suitable for
validation using dependency diagrams.
Design new areas of your application
When you start development of a new project, or a new area in a new project, you can draw layers and
dependencies to help identify the major components before you start to develop the code.
Show identifiable architectural patterns in your dependency diagrams, if possible. For example, a
dependency diagram that describes a desktop application might include layers such as Presentation,
Domain Logic, and Data Store. A dependency diagram that covers a single feature within an application
might have layers such as Model, View, and Controller. For more information about such patterns, see
Patterns & Practices: Application Architecture.
Create a code artifact for each layer such as a namespace, class, or component. This makes it easier to
follow the code and to link the code artifacts to layers. As soon as you create each artifact, link it to the
appropriate layer.
You do not have to link most classes and other artifacts to layers because they fall within larger
artifacts such as namespaces that you have already linked to layers.
Create a new diagram for a new feature. Typically, there will be one or more dependency diagrams
describing the whole application. If you are designing a new feature within the application, do not add to
or change the existing diagrams. Instead, create your own diagram that reflects the new parts of the code.
The layers in the new diagram might include presentation, domain logic, and database layers for the new
feature.
When you build the application, your code will be validated both against the overall diagram and your
more detailed feature diagram.

Edit the layout for presentation and discussion


To help you identify layers and dependencies or discuss them with team members, edit the appearance and
layout of the diagram in the following ways:
Change the sizes, shapes, and positions of layers.
Change the colors of layers and dependencies.
Select one or more layers or dependencies, right-click, and then click Properties. In the Properties
window, edit the Color property.

Validate the code against the diagram


When you have edited the diagram, you can validate it against the code manually at any time or automatically
every time that you run a local build or Team Foundation Build.
See:
Validate code with dependency diagrams
Include Layer Validation in the Build Process

Update the code to conform to the new architecture


Typically, errors will appear the first time that you validate code against an updated dependency diagram. These
errors can have several causes:
An artifact is assigned to the wrong layer. In this case, move the artifact.
An artifact, such as a class, uses another class in a way that conflicts with your architecture. In this case,
refactor the code to remove the dependency.
To resolve these errors, update the code until no more errors appear during validation. This is usually an
iterative process. For more information about these errors, see Validate code with dependency diagrams.

NOTE
As you develop or refactor the code, you might have new artifacts to link to the dependency diagram. However, this
might not be necessary, for example, when you have layers that represent existing namespaces, and the new code only
adds more material to those namespaces.

During the development process, you might want to suppress some of the reported conflicts during validation.
For example, you might want to suppress errors that you are already addressing or that are not relevant to your
particular scenario. When you suppress an error, it is a good practice to log a work item in Team Foundation. To
perform this task, see Validate code with dependency diagrams.

Include layer validation in the build process


To ensure that future changes in the code conform to the dependency diagrams, include layer validation to your
solution's standard build process. Whenever other team members build the solution, any differences between
the dependencies in the code and the dependency diagram will be reported as build errors. For more
information about including layer validation in the build process, see Validate code with dependency diagrams.

See Also
Dependency Diagrams: Reference
Create dependency diagrams from your code
Share models and exporting diagrams
11/7/2017 1 min to read Edit Online

In Visual Studio, you can share models and diagrams with colleagues in several ways.
To see which versions of Visual Studio support this feature, see Version support for architecture and modeling
tools.

Working on a Model as a Team


Users of Visual Studio can create and edit models, dependency diagrams, and directed graphs.
Different users can work at the same time on a model, but should work on different packages.
We recommend that you use Team Foundation version control.
For suggestions about organizing models in a medium or large project, see Structure your modeling solution.

Reading and Reviewing Models


Team members using some versions of Visual Studio (which cannot create models) can read models, modeling
diagrams, and directed graphs, but cannot edit them. To see which versions of Visual Studio support this feature,
see Version support for architecture and modeling tools.
A dependency diagram can be opened only within the model in which it was created. To provide access to a
diagram, you must therefore provide access to all the modeling project files, or to copies of them.
For more information, see Read models and diagrams in other Visual Studio editions.

Using Diagrams in Documents and Presentations


You can copy parts of diagrams into documents or presentations. You can also print diagrams, for example to XPS
files.
For more information, see Export diagrams as images.

Related Topics
TITLE DESCRIPTION

Structure your modeling solution Sharing models in a large or medium project.

Export diagrams as images You can copy parts of diagrams into applications such as
PowerPoint or Word, or print a diagram to an XPS file.

Analyzing and Modeling Architecture Overview of models and diagrams.

See Also
Use models in your development process
Read models and diagrams in other Visual Studio
editions
10/18/2017 1 min to read Edit Online

When you open a model in a version of Visual Studio that does not support model creation, the model opens in
read-only mode. In this mode, you can change the layout of the diagrams, but you cannot change the model.
To see which versions of Visual Studio support model creation, see Version support for architecture and modeling
tools.

Obtaining Access to a Model and Diagrams


To read a dependency diagram, you must first use Visual Studio to open the modeling project, and then open the
diagram within it.
For this reason, if you want to read a dependency diagram, you must also have access to the modeling project in
which it was created. You can do this either by accessing the project from Team Foundation version control, or by
obtaining a copy of the project files.

NOTE
This does not apply to code maps and .NET class diagrams generated from code. Those diagrams can be viewed
independently of a modeling project.

To read a dependency diagram, the minimum set of files that you need is as follows:
The two diagram files for the diagram that you want to read, for example, MyDiagram.classdiagram and
MyDiagram.classdiagram.layout.

NOTE
For dependency diagrams, you should also have the file that is named MyDiagram.layerdiagram.suppressions.

The modeling project file (MyModel.modelproj)


The root model file (ModelDefinition\MyModel.uml)
The package files for any package referenced in the diagram (ModelDefinition\MyPackage.uml)

Changes that you can Make in Read-Only Mode


If you open a model and its diagrams in a version of Visual Studio that does not support model creation, you
cannot change the model. That is, you cannot change the elements and relationships that are displayed on the
diagrams or in the model explorer. However, you can make some changes to the layout of the diagrams:
Rearrange the shapes and connectors on the diagram.
Expand and collapse shapes.
You can save these changes. If you want to make your changes visible to other users, you must at least send
the updated .layout files.
Related Topics
TITLE DESCRIPTION

Dependency Diagrams: Reference A layer diagram shows the structure of an existing or


proposed architecture. When code is written, it can be
automatically validated against a layer diagram.

See Also
Create models for your app
Export diagrams as images
10/18/2017 1 min to read Edit Online

In Visual Studio, you can save modeling diagrams in read-only formats so that you can share them with
stakeholders, users, or project team members who do not use the same version of Visual Studio.
To see which versions of Visual Studio support this feature, see Version support for architecture and modeling
tools.
To copy a diagram or part of a diagram to another application
1. On the diagram, select some or all the shapes.
2. Right-click your selection, and then click Copy.
3. Paste your selection into the application that you want.
To save a modeling diagram as an XML Paper Specification (.xps) file
1. On the File menu, click Print to open the Print dialog box.
2. In the Name list, select Microsoft XPS Document Writer, and then click OK.
3. In the Save the file as dialog box, save the file as an XPS Document (*.xps) file.

.NET Framework Security


See Also
Create models for your app
Share models and exporting diagrams
Use models in your development process
11/7/2017 10 min to read Edit Online

In Visual Studio, you can use a model to help you understand and change a system, application, or component. A
model can help you visualize the world in which your system works, clarify users' needs, define the architecture
of your system, analyze the code, and ensure that your code meets the requirements. See Channel 9 Video:
Improve architecture through modeling.
To see which versions of Visual Studio support each type of model, see Version support for architecture and
modeling tools.

How to use models


Models can help you in several ways:
Drawing modeling diagrams helps you clarify the concepts involved in requirements, architecture, and
high-level design. For more information, see Model user requirements.
Working with models can help you expose inconsistencies in requirements.
Communicating with models helps you communicate important concepts less ambiguously than with
natural language. For more information, see Model your app's architecture.
You can sometimes use models to generate code or other artifacts such as database schemas or
documents. For example, the modeling components of Visual Studio Ultimate are generated from a model.
For more information, see Generate and configure your app from models.
You can use models in a wide variety of processes, from extreme agile to high ceremony.
Use Models to Reduce Ambiguity
Modeling language is less ambiguous than natural language, and it is designed to express the ideas typically
required during software development.
If your project has a small team following agile practices, you can use models to help you clarify user stories. In
discussions with the customer about their needs, creating a model can generate useful questions much faster,
and across a broader area of the product, than writing spike or prototype code.
If your project is large and includes teams in different parts of the globe, you can use models to help
communicate the requirements and architecture much more effectively than you can in plain text.
In both cases creating a model almost always results in a significant reduction in inconsistencies and ambiguities.
Different stakeholders frequently have different understandings of the business world in which the system works,
and different developers frequently have different understandings of how the system works. Using a model as
the focus of a discussion usually exposes these differences. For more information about how to use a model to
reduce inconsistencies, see Model user requirements.
Use Models with Other Artifacts
A model is not by itself a requirements specification or an architecture. It is a tool for expressing some aspects of
these things more clearly, but not all the concepts required during software design can be expressed. The models
should therefore be used together with other means of communication, such as OneNote pages or paragraphs,
Microsoft Office documents, work items in Team Foundation, or sticky notes on the project room wall. Apart from
the last item, all of these object types can be linked to elements parts of the model.
Other aspects of specification that are ordinarily used together with models include the following. Depending on
the scale and style of your project, you might use several of these aspects or not use any at all:
User stories. A user story is a short description, discussed with users and other stakeholders, of an aspect
of the system's behavior that will be delivered in one of the project's iterations. A typical user story begins
"The customer will be able to...." A user story might introduce a group of use cases, or can define
extensions of use cases that have been previously developed. Defining or extending the use cases helps
make the user story clearer.
Change Requests. A change request in a more formal project is very similar to a user story in an agile
project. The agile approach treats all requirements as changes to what was developed in previous
iterations.
Use case description. A use case represents one way in which a user interacts with the system to achieve a
particular goal. A full description includes the goal, main and alternative sequences of events, and
exceptional outcomes. A use case diagram helps summarize and provide an overview of the use cases.
Scenarios. A scenario is a fairly detailed description of a sequence of events showing how the system,
users and other systems work together to provide value to the stakeholders. It might take the form of a
slide show of the user interface or a prototype of the user interface. It can describe one use case or a
sequence of use cases.
Glossary. The project's requirements glossary describes the words with which customers discuss their
world. The user interface and requirements models should also use these terms. A class diagram can help
clarify the relationships between most of these terms. Creating the diagrams and glossary not only
reduces misunderstandings between users and developers, but also almost always exposes
misunderstandings between different business stakeholders.
Business rules. Many business rules can be expressed as invariant constraints on the associations and
attributes in the requirements class model, and as constraints on sequence diagrams.
High-level design. Describes the major parts and how they fit together. Component, sequence and
interface diagrams are a major part of a high-level design.
Design patterns. Describe the rules of design that are shared across the different parts of the system.
Test specifications. Test scripts and the designs for test code can make good use of activity and sequence
diagrams to describe sequences of test steps. System tests should be expressed in terms of the
requirements model so that they can easily be changed when the requirements change.
Project plan. The project plan or backlog defines when each feature will be delivered. You can define each
feature by stating what use cases and business rules it implements or extends. You can either refer to the
use cases and business rules directly in the plan, or you can define a set of features in a separate
document, and use the feature titles in the plan.
Use Models in Iteration Planning
Although all projects are different in their scale and organization, a typical project is planned as a series of
iterations of between two and six weeks. It is important to plan enough iterations to allow feedback from early
iterations to be used to adjust the scope and plans for later iterations.
You might find the following suggestions useful to help realize the benefits of modeling in an iterative project.
Sharpen Focus as each Iteration Approaches
As each iteration approaches, use models to help define what is to be delivered at the end of the iteration.
Do not model everything in detail in the early iterations. In the first iteration, create a class diagram for the
main items in the user glossary, draw a diagram of the major use cases, and draw a diagram of the major
components. Do not describe any of these in fine detail, because the detail will change later in the project.
Use the terms defined in this model to create a list of features or major user stories. Assign the features to
iterations so as to approximately balance the estimated workload throughout the project. These
assignments will change later in the project.
Try to implement simplified versions of all the most important use cases in an early iteration. Extend those
use cases in later iterations. This approach helps reduce the risk of discovering a flaw in the requirements
or the architecture too late in the project to do anything about it.
Near the end of each iteration, hold a requirements workshop to define in detail the requirements or user
stories that will be developed in the next iteration. Invite users and business stakeholders who can decide
priorities, as well as developers and system testers. Allow three hours to define requirements for a 2-week
iteration.
The objective of the workshop is for everyone to agree what will be accomplished by the end of the next
iteration. Use models as one of the tools to help clarify the requirements. The output of the workshop is an
iteration backlog: that is, a list of development tasks in Team Foundation and test suites in Microsoft Test
Manager.
In the requirements workshop, discuss the design only insofar as you need to determine estimates for the
development tasks. Otherwise, keep discussion to system behavior that users can experience directly. Keep
the requirements model separate from the architectural model.
Nontechnical stakeholders usually have no problems understanding UML diagrams, with some guidance
from you.
Link Model to Work Items
After the requirements workshop, elaborate the details of the requirements model, and link the model to
development tasks. You can do this by linking work items in Team Foundation to elements in the model.
You can link any element to work items, but the most useful elements are as follows:
Comments describing business rules or quality of service requirements. For more information, see Model user
requirements.
Link Model to Tests
Use the requirements model to guide the design of the acceptance tests. Create these tests concurrently with the
development work.
To learn more about this technique, see Develop tests from a model.
Estimate Remaining Work
A requirements model can help estimate the total size of the project in relation to the size of each iteration.
Assessing the number and complexity of the use cases and classes can help you estimate the development work
that will be required. When you have completed the first few iterations, a comparison of the requirements
covered and the requirements still to cover can give an approximate measure of the cost and scope of the rest of
the project.
Near the end of each iteration, review the assignment of requirements to future iterations. It can be useful to
represent the state of your software at the end of each iteration as a subsystem in a use case diagram. In your
discussions, you can move use cases and use case extensions from one of these subsystems to another.

Levels of abstraction
Models have a range of abstraction in relation to the software. The most concrete models directly represent
program code, and the most abstract models represent business concepts that might or might not be represented
in the code.
A model can be viewed through several kinds of diagrams. For information about models and diagrams, see
Create models for your app.
Different kinds of diagram are useful for describing the design at different levels of abstraction. Many of the
diagram types are useful at more than one level. This table shows how each type of diagram can be used.

DESIGN LEVEL DIAGRAM TYPES

Business Process - Conceptual class diagrams describe the business concepts


used within the business process.
Understanding the context within which your system will be
used helps you understand what the users need from it.

User requirements - Business rules and quality of service requirements can be


described in separate documents.
Definition of what the users need from your system.

High level design - Dependency Diagrams describe how the system is


structured into interdependent parts. You can validate
The overall structure of the system: the major components program code against dependency diagrams to ensure that it
and how they couple together. adheres to the architecture.

Code analysis - Dependency diagrams show the dependencies between


classes. Updated code can be validated against a dependency
Diagrams can be generated from the code. diagram.
- Class diagrams show the classes in the code.

External Resources
CATEGORY LINKS

Videos MSDN How Do I Videos: How to Create and Use UML


Models and Diagrams (Visual Studio 2010 Ultimate)

Channel 9: UML with Visual Studio 2010

MSDN How Do I Series: UML Tools and Extensibility


(Visual Studio 2010 Ultimate)

Forums - Visual Studio Visualization & Modeling Tools


- Visual Studio Visualization & Modeling SDK (DSL Tools)

Blogs Visual Studio ALM + Team Foundation Server Blog

Technical Articles and Journals MSDN Architecture Center

Visual Studio Architecture Tooling Guidance

See Also
Use models in Agile development
Create models for your app
Model user requirements
Model your app's architecture
Develop tests from a model
Structure your modeling solution
In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK
are installed automatically when you install specific features of Visual Studio. For more details, see this blog
post.
Model user requirements
10/18/2017 4 min to read Edit Online

Visual Studio helps you understand, discuss, and communicate your users' needs by drawing diagrams about
their activities and the part your system plays in helping them achieve their goals. A requirements model is a set
of these diagrams, each of which focuses on a different aspect of the users' needs. For a video demonstration,
see: Modeling the Business Domain.
To see which versions of Visual Studio support each type of model, see Version support for architecture and
modeling tools.
A requirements model helps you:
Focus on the system's external behavior, separately from its internal design.
Describe the users' and stakeholders' needs with much less ambiguity than you can in natural language.
Define a consistent glossary of terms that can be used by users, developers, and testers.
Reduce gaps and inconsistencies in the requirements.
Reduce the work needed to respond to requirements changes.
Plan the order in which features will be developed.
Use the models as a basis for system tests, making a clear relationship between the tests and the
requirements. When the requirements change, this relationship helps you update the tests correctly. This
makes sure that the system meets the new requirements.
A requirements model provides greatest benefit if you use it to focus discussions with the users or their
representatives, and revisit it at the beginning of each iteration. You do not have to complete it in detail
before writing code. A partially working application, even if very much simplified, generally forms the
most stimulating basis for discussion of the requirements with users. The model is an effective way to
summarize the results of those discussions. For more information, see Use models in your development
process.

NOTE
Throughout these topics, "system" means the system or the application that you are developing. It might be a large
collection of many software and hardware components; or a single application; or a software component inside a larger
system. In every case, the requirements model describes the behavior that is visible from outside your system, whether
through a user interface or API.

Common Tasks
You can create several different views of the users' requirements. Each view provides a particular type of
information. When you create these views, it is best to move frequently from one to another. You can start from
any view.

WHAT IT DESCRIBES IN A REQUIREMENTS


DIAGRAM OR DOCUMENT MODEL SECTION
WHAT IT DESCRIBES IN A REQUIREMENTS
DIAGRAM OR DOCUMENT MODEL SECTION

Conceptual class diagram Glossary of types that are used to


describe the requirements; the types
visible at the system's interface.

Additional documents or work items Performance, security, usability and Describing quality of service
reliability criteria. requirements

Additional documents or work items Constraints and rules not specific to a Showing business rules
particular use case

Notice that most of the diagram types can be used for other purposes. For an overview of diagram types, see
Create models for your app.

Showing Business Rules


A business rule is a requirement that is not associated with a particular use case, and should be observed
throughout the system.
Many business rules are constraints on the relationships among the conceptual classes. You can write these
staticbusiness rules as comments associated with the relevant classes on a conceptual class diagram. For example:

Dynamic business rules constrain the allowable sequences of events. For example, you use a sequence or activity
diagram to show that a user must log in before performing other operations on your system.
However, many dynamic rules can be more effectively and generically stated by replacing them with static rules.
For example, you could add a Boolean attribute 'Logged In' to a class in the conceptual class model. You would
add Logged In as the postcondition of the log in use case, and add it as a precondition of most of the other use
cases. This approach lets you avoid defining all the possible combinations of sequences of events. It is also more
flexible when you need to add new use cases to the model.
Notice that the choice here is about how you define the requirements, and that this is independent of how you
implement the requirements in the program code.
The following topics provide more information:

TO LEARN ABOUT READ

How to develop code that adheres to business rules Model your app's architecture

Describing Quality of Service Requirements


There are several categories of quality of service requirement. They include the following:
Performance
Security
Usability
Reliability
Robustness
You can include some of these requirements in the descriptions of particular use cases. Other
requirements are not specific to use cases, and are most effectively written in a separate document. When
you can, it is useful to adhere to the vocabulary defined by the requirements model. In the following
example, notice that the main words used in the requirement are the titles of actors, use cases, and classes
in the preceding illustrations:
If a Restaurant deletes a Menu Item while a Customer is Ordering a Meal, any Order Item that refers to
that Menu Item will be displayed in red.
The following topics provide more information:

TO LEARN ABOUT READ

More detailed information about recording quality of service Guidelines for Defining Quality of Service Requirements
requirements

How to develop code that adheres to quality of service Model your app's architecture
requirements

See Also
Use models in your development process
Model your app's architecture
Model your app's architecture
10/18/2017 7 min to read Edit Online

To help ensure that your software system or application meets your users' needs, you can create models in
Visual Studio as part of your description of the overall structure and behavior of your software system or
application. Using models, you can also describe patterns that are used throughout the design. These models
help you understand the existing architecture, discuss changes, and communicate your intentions clearly.
To see which versions of Visual Studio support this feature, see Version support for architecture and modeling
tools.
The purpose of a model is to reduce the ambiguities that occur in natural-language descriptions, and to help you
and your colleagues to visualize the design and to discuss alternative designs. A model should be used together
with other documents or discussions. By itself, a model does not represent a complete specification of the
architecture.

NOTE
Throughout this topic, "system" means the software that you are developing. It might be a large collection of many
software and hardware components, or a single application, or a part of an application.

The architecture of a system can be divided into two areas:


High-level Design. This describes the major components and how they interact with one another to fulfill
each requirement. If the system is large, each component might have its own high-level design that shows
how it is composed of smaller components.
Design Patterns and conventions used throughout the designs of the components. A pattern describes a
particular approach to achieving a programming goal. By using the same patterns throughout a design,
your team can reduce the cost of making changes and developing new software.

High-level Design
A high-level design describes the major components of your system and how they interact with one another to
achieve the goals of the design. The activities in the following list are involved in developing the high level
design, although not necessarily in a particular sequence.
If you are updating existing code, you might begin by describing the major components. Make sure you
understand any changes to the user requirements and then add or modify interactions between the components.
If you are developing a new system, begin by understanding the main features of the users' needs. You can then
explore sequences of interactions for the main use cases, and then consolidate the sequences into a component
design.
In every case, it is helpful to develop the different activities in parallel, and to develop code and tests at an early
stage. Avoid trying to complete one of these aspects before you start another. Typically, both the requirements
and your understanding of the best way to design the system will change while you are writing and testing the
code. Therefore, you should begin by understanding and coding the main features of the requirements and your
design. Fill in the details in later iterations of the project.
Understanding the Requirements. The starting point of any design is a clear understanding of the users'
needs.
Architectural Patterns. The choices you made about core technologies and architectural elements of the
system.
Data Model of the Components and Interfaces. You can draw class diagrams to describe the information
that is passed between components and stored inside the components.

Understanding the Requirements


The high-level design of a complete application is most effectively developed together with a requirements
model or other description of the users' needs. For more information about requirements models, see Model
user requirements.
If the system that you are developing is a component in a larger system, part or all of your requirements might
be embodied in programmatic interfaces.
The requirements model provides these essential pieces of information:
Provided interfaces. A provided interface lists the services or operations that the system or component
must provide to its users, whether they are human users or other software components.
Required interfaces. A required interface lists the services or operations that the system or component can
use. In some cases, you will be able to design all these services as part of your own system. In other cases,
especially if you are designing a component that can be combined with other components in many
configurations, the required interface will be set by external considerations.
Quality of service requirements. The performance, security, robustness, and other goals and constraints
that the system must meet.
The requirements model is written from the point of view of your system's users, whether they are people
or other software components. They know nothing of the internal workings of your system. By contrast,
your goal in an architectural model is to describe the internal workings and show how they meet the
users' needs.
Keeping the requirements and architectural models separate is useful because it makes it easier to discuss
the requirements with the users. It also helps you refactor the design and consider alternative
architectures while keeping the requirements unchanged.
The amount of detail that you should put into either a requirements or an architectural model depends on
the scale of the project and the size and distribution of the team. A small team on a short project might go
no further than sketching a class diagram of the business concepts and some design patterns; a large
project distributed over more than one region would need significantly more detail.

Architectural Patterns
Early in a development, you have to choose the major technologies and elements on which the design depends.
The areas in which these choices must be made include the following:
Base technology choices, such as the choice between a database and a file system, and the choice between
a networked application and a Web client, and so on.
Frameworks choices, such as a choice between Windows Workflow Foundation or ADO.NET Entity
Framework.
Integration method choices, for example between an enterprise service bus or a point-to-point channel.
These choices are frequently determined by quality of service requirements such as scale and flexibility,
and can be made before the detailed requirements are known. In a large system, the configuration of
hardware and software are strongly interrelated.
The selections that you make affect how you use and interpret the architectural model. For example, in a
system that uses a database, associations in a class diagram might represent relations or foreign keys in
the database, whereas in a system that is based on XML files, associations might indicate cross-references
that use XPath. In a distributed system, messages in a sequence diagram can represent messages on a
wire; in a self-contained application, they can represent function calls.

Design Patterns
A design pattern is an outline of how to design a particular aspect of the software, especially one that recurs in
different parts of the system. By adopting a uniform approach across the project, you can reduce the cost of
design, ensure consistency in the user interface, and reduce the cost of understanding and changing the code.
Some general design patterns such as Observer are well-known and widely applicable. In addition, there are
patterns that are applicable just to your project. For example, in a Web sales system, there will be several
operations in the code where changes are made to a customer's order. To ensure that the state of the order is
accurately displayed at every stage, all these operations must follow a particular protocol to update the database.
Part of the work of software architecture is to determine what patterns should be adopted across the design. This
is usually an ongoing task, because new patterns and improvements to existing patterns will be discovered as
the project progresses. It is helpful to organize the development plan so that you exercise each of your major
design patterns at an early stage.
Most design patterns can be partly embodied in framework code. Part of the pattern can be reduced to requiring
the developer to use particular classes or components, such as a database access layer that ensures the database
is handled correctly.
A design pattern is described in a document, and typically includes these parts:
Name.
Description of the context in which it is applicable. What criteria should make a developer consider
applying this pattern?
Brief explanation of the problem it solves.
Model of the major parts and their relationships. These might be classes or components and interfaces,
with associations and dependencies between them. The elements usually fall into two categories:
Naming conventions.
Description of how the pattern solves the problem.
Description of variations that developers might be able to adopt.

See Also
Visualize code
Model user requirements
Develop tests from a model
Use models in your development process
Generate and configure your app from models
10/18/2017 5 min to read Edit Online

You can generate or configure parts of your application from a model.


The model represents the requirements more directly than the code. By deriving the application's behavior directly
from the model, you can respond to changed requirements much more quickly and reliably than by updating the
code. Although some initial work is required to set up the derivation, this investment is returned if you expect
changes in requirements, or if you plan to make several variants of the product.

Generating the Code of your Application from a Model


The easiest way to generate code is by using text templates. You can generate code in the same Visual Studio
solution in which you keep the model. For more information, see:
Design-Time Code Generation by using T4 Text Templates
Generating Code from a Domain-Specific Language
This method is easy to apply incrementally. Start with an application that works only for a specific case, and
choose a few parts of it that you want to vary from the model. Rename the source files of these parts so that
they become text template (.tt) files. At this point, the source .cs files will automatically be generated from
the template files, so the application will work as it did before.
Then you can take one part of the code and replace it with a text template expression, which reads the model
and generates that part of the source file. At least one value of the model should generate the original
source so that again you can run the application and it will work as before. After you test different model
values, you can move on to insert template expressions in another part of the code.
This incremental method means that code generation is usually a low-risk approach. The resulting
applications usually perform almost as well as a hand-written version.
However, if you start with an existing application, you might find that a lot of refactoring is required to
separate the different behaviors that are governed by the model so that they can be independently varied.
We recommend that you assess this aspect of the application when you estimate the cost of your project.

Configuring your Application from a Model


If you want to vary your application's behavior at run time, you cannot use code generation, which generates
source code before the application is compiled. Instead, you can design your application to read the model, and to
vary its behavior accordingly. For more information, see:
How to: Open a Model from File in Program Code
This method can also be applied incrementally, but there is more work at the beginning. You need to write
the code that will read the model, and set up a framework that allows its values to be accessible to the
variable parts. Making the variable parts generic is more expensive than code generation.
A generic application usually performs less well than its specific counterparts. If performance is crucial, your
project plan should include an assessment of this risk.

Developing a Derived Application


You might find the following general guidelines useful.
Start specific, then generalize. Write a specific version of your application first. This version should work
in one set of conditions. When you are satisfied that it is working correctly, you can make some of it derive
from a model. Extend the derived parts gradually.
For example, design a Web site that has a specific set of Web pages before you design a Web application
that presents pages that are defined in a model.
Model the variant aspects. Identify the aspects that will vary, either between one deployment and another,
or over time as requirements change. These are the aspects that should be derived from a model.
For example, if the set of Web pages and links between them changes, but the style and format of the pages
is always the same, then the model should describe the links, but does not have to describe the format of the
pages.
Separate concerns. If the variable aspects can be divided into independent areas, use separate models for
each area. Using ModelBus, you can define operations that affect both models, and constraints between
them.
For example, use one model to define navigation between the Web pages and a different model to define
the layout of the pages.
Model the requirement, not the solution. Design the model so that it describes the user requirements.
By contrast, do not design the notation according to the variable aspects of the implementation.
For example, the Web navigation model should represent Web pages and hyperlinks between them. The
Web navigation model should not represent fragments of HTML or classes in your application.
Generate or interpret? If the requirements for a particular deployment will rarely change, generate
program code from the model. If the requirements might frequently change, or might co-exist in more than
one variant in the same deployment, write the application so that it can read and interpret a model.
For example, if you use your Web site model to develop a series of different and separately-installed Web
sites, then you should generate the code of the site from the model. But it you use your model to control a
site that changes every day, then it is better to write a Web server that reads the model and presents the site
accordingly.
UML or DSL? Consider creating your modeling notation by using stereotypes to extend UML. Define a DSL
if there is no UML diagram that fits the purpose. But avoid breaking the standard semantics of UML.
For example, a UML class diagram is a collection of boxes and arrows; with this notation you can in theory
define anything. But we do not recommend that you use the class diagram except where you are in fact
describing a set of types. For example, you could adapt class diagrams to describe different types of Web
pages.

See Also
Generating Code from a Domain-Specific Language
How to: Open a Model from File in Program Code
Design-Time Code Generation by using T4 Text Templates
Structure your modeling solution
11/7/2017 6 min to read Edit Online

To use models effectively in a development project, the team members must be able to work on models of
different parts of the project at the same time. This topic suggests a scheme for dividing the application into
different parts that correspond to the layers in an overall layering diagram.
To start on a project or subproject quickly, it is useful to have a project template that follows the project structure
that you have chosen. This topic describes how to create and use such a template.
This topic assumes that you are working on a project that is large enough to require several team members, and
perhaps has several teams. The code and models of the project are stored on a source control system such as
Team Foundation Server. At least some team members use Visual Studio to develop models, and other team
members can view the models by using other Visual Studio versions.
To see which versions of Visual Studio support each tool and modeling feature, see Version support for
architecture and modeling tools.

Solution structure
In a medium or large project, the structure of the team is based on the structure of the application. Each team uses
a Visual Studio solution.
To divide an application into layers
1. Base the structure of your solutions on the structure of your application, such as web application, service
application, or desktop application. A variety of common architectures is discussed in Application
Archetypes in the Microsoft Application Architecture Guide.
2. Create a Visual Studio solution, which we will call the Architecture solution. This solution will be used to
create the overall design of the system. It will contain models but no code.
Add a dependency diagram to this solution. On the dependency diagram, draw the architecture you have
chosen for your application. For example, the diagram might show these layers and the dependencies
between them: Presentation; Business logic; and Data.
3. Create a separate Visual Studio solution for each layer in the Architecture dependency diagram.
These solutions will be used to develop the code of the layers.
4. Create models that will represent the designs of the layers and the concepts that are common to all the
layers. Arrange the models so that all the models can be seen from the Architecture solution, and the
relevant models can be seen from each layer.
You can achieve this by using either of the following procedures. The first alternative creates a separate
modeling project for each layer, and the second creates a single modeling project that is shared between
the layers.
To u s e a s e p a ra t e mo d e l i n g p ro j e c t f o r e a c h l a y e r

a. Create a modeling project in each layer solution.


This model will contain diagrams that describe the requirements and design of that layer. It can also
contain dependency diagrams that show nested layers.
You now have a model for each layer, plus a model for the application architecture. Each model is
contained in its own solution. This enables team members to work on the layers at the same time.
b. To the Architecture solution, add the modeling project of each layer solution. To do this, open the
Architecture solution. In Solution Explorer, right-click the solution node, point to Add, and then click
Existing Project. Navigate to the modeling project (.modelproj) in one layer solution.
Each model is now visible in two solutions: its "home" solution and the Architecture solution.
c. To the modeling project of each layer, add a dependency diagram. Start with a copy of the
Architecture dependency diagram. You can delete parts that are not dependencies of the dependency
diagram.
You can also add dependency diagrams that represent the detailed structure of this layer.
These diagrams are used to validate the code that is developed in this layer.
d. In the Architecture solution, edit the requirements and design models of all the layers by using Visual
Studio.
In each layer solution, develop the code for that layer, referring to the model. If you are content to do
the development without using the same computer to update the model, you can read the model
and develop code by using versions of Visual Studio that cannot create models. You can also
generate code from the model in these versions.
This method guarantees that no interference will be caused by developers who edit the layer models
at the same time.
However, because the models are separate, it is difficult to refer to common concepts. Each model
must have its own copy of the elements on which it is dependent from other layers and the
architecture. The dependency diagram in each layer must be kept in sync with the Architecture
dependency diagram. It is difficult to maintain synchronization when these elements change,
although you could develop tools to accomplish this.
To u s e a s e p a ra t e p a c k a g e f o r e a c h l a y e r

a. In the solution for each layer, add the Architecture modeling project. In Solution Explorer, right-click
the solution node, point to Add, and then click Existing Project. The single modeling project can
now be accessed from every solution: the Architecture project, and the development project for each
layer.
b. In the shared model, create a package for each layer: In Solution Explorer, select the modeling
project. In UML Model Explorer, right-click the model root node, point to Add, and then click
Package.
Each package will contain diagrams that describe the requirements and design of the corresponding
layer.
c. If required, add local dependency diagrams for the internal structure of each layer.
This method allows the design elements of each layer to refer directly to those of the layers and
common architecture on which it depends.
Although concurrent work on different packages can cause some conflicts, they are fairly easy to
manage because the packages are stored in separate files.

Creating architecture templates


In practice, you will not create all your Visual Studio solutions at the same time, but add them as the project
progresses. You will probably also use the same solution structure in future projects. To help you create new
solutions quickly, you can create a solution or project template. You can capture the template in a Visual Studio
Integration Extension (VSIX) so that it is easy to distribute and to install on other computers.
For example, if you frequently use solutions that have Presentation, Business, and Data layers, you can configure a
template that will create new solutions that have that structure.
To create a solution template
1. Download and install the Export Template Wizard, if you have not already done this.
2. Create the solution structure that you want to use as a starting point for future projects.
3. On the File menu, click Export Template as VSIX. The Export Template as VSIX Wizard opens.
4. Following the instructions in the wizard, select the projects that you want to include in the template, provide
a name and description for the template, and specify an output location.

NOTE
The material in this topic is abstracted and paraphrased from the Visual Studio Architecture Tooling Guidance, written by the
Visual Studio ALM Rangers, which is a collaboration between Most Valued Professionals (MVPs), Microsoft Services, and the
Visual Studio product team and writers. Click here to download the complete Guidance package.

Related materials
Organizing and Managing Your Models - video by Clint Edmondson.
Visual Studio Architecture Tooling Guidance - Further guidance on managing models in a team

See Also
Use models in your development process
Visual Studio Architecture Tooling Guidance
10/18/2017 1 min to read Edit Online

This Architecture Tooling Guidance is a downloadable package of practical guidance about the use of the modeling
tools in Visual Studio 2010. It presents a high-level view of how to use all the modeling tools in an integrated
manner, and discusses the most common scenarios in which the tools are used.
The content was created by the Visual Studio ALM Rangers, a special group that has members from the Visual
Studio Product Team, Microsoft Services, Microsoft Most Valued Professionals (MVPs), and Visual Studio
Community Leads.
Click here to download the Architecture Tooling Guidance..
Validate your system during development
10/18/2017 1 min to read Edit Online

Visual Studio can help keep your software consistent with the users' requirements and with the architecture of
your system.
To see which versions of Visual Studio support each of these features, see Version support for architecture and
modeling tools.

Key Tasks
Use the following tasks to validate your software.

TASKS ASSOCIATED TOPICS

Make sure your software meets the users' requirements: - Develop tests from a model

You can use requirements and architectural models to help


you organize the tests of your system and its components.
This practice helps ensure that you test the requirements that
are important to the users and other stakeholders, and it
helps you update the tests quickly when the requirements
change.

Make sure that your software remains consistent with the - Create dependency diagrams from your code
intended design of your system: - Validate code with dependency diagrams

Dependency diagrams describe the intended dependencies


between the components of your application. During
development, you can verify that the actual dependencies in
the code conform to the intended design.

External Resources
CATEGORY LINKS

Videos Channel 9: Doug Seven: Code Understanding and System


Design with Visual Studio 2010

Channel 9: Architecting an Application using a


Dependency Diagram

MSDN How Do I Series: How to Validate Code using


Dependency Diagrams

Forums - Visual Studio Visualization & Modeling Tools


- Visual Studio Visualization & Modeling SDK (DSL Tools)

Blogs - Visual Studio ALM + Team Foundation Server Blog

Technical Articles and Journals MSDN Architecture Center


See Also
Testing the application
Model user requirements
Analyzing and Modeling Architecture

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.
Develop tests from a model
11/7/2017 11 min to read Edit Online

You can use requirements and architectural models to help you organize the tests of your system and its
components. This practice helps ensure that you test the requirements that are important to the users and other
stakeholders, and it helps you update the tests quickly when the requirements change. If you use Microsoft Test
Manager, you can also maintain links between the models and the tests.
To see which versions of Visual Studio support these features, see Version support for architecture and modeling
tools.

System and Subsystem Testing


System testing, also known as acceptance testing, means testing whether the users' needs are being met. Such
tests are concerned about the externally visible behavior of the system instead of the internal design.
System tests are very valuable when extending or redesigning a system. They help you avoid introducing bugs
when you change the code.
When you plan any change or extension to a system, it is helpful to start with a set of system tests that run on the
existing system. Then you can extend or adjust the tests to test the new requirements, make the changes to the
code, and rerun the complete set of tests.
When you develop a new system, you can begin to create tests as soon as development begins. By defining tests
before you develop each feature, you can capture the requirements discussions in a very specific way.
Subsystem testing applies the same principles to the major components of a system. Each component is tested
separately from other components. Subsystem tests focus on the behavior visible at the component's user
interfaces or API.

Deriving System Tests from a Requirements Model


You can create and maintain a relationship between system tests and a requirements model. To establish this
relationship, you write tests that correspond to the main elements of the requirements model. Visual Studio helps
you maintain that relationship by letting you create links between the tests and parts of the model. For more
information about requirements models, see Model user requirements.
Write Tests for Each Use Case
If you use Microsoft Test Manager, you can create a group of tests for each use case that you defined in your
requirements model. For example, if you have a use case Order a Meal, which includes Create Order and Add Item
to Order, you can create tests for both the overall and the more detailed of these use cases.
These guidelines might be helpful:
Each use case should have several tests, for main paths and exceptional outcomes.
When you describe a use case in the requirements model, it is more important to define its postcondition,
that is, the goal that is achieved, than to describe in detail the procedures the user follows in order to
achieve the goal. For example, the postcondition of Order a Meal might be that a Restaurant is preparing a
meal for a Customer and that the Customer has paid. The postcondition is the criterion that your tests
should verify.
Base separate tests on the separate clauses of the postcondition. For example, create separate tests for
notifying the restaurant of the order, and for taking payment from the customer. This separation has these
advantages:
Changes in different aspects of the requirements frequently occur independently. By separating the
tests into different aspects in this manner, you make it easier to update the tests when requirements
change.
If the development plan implements one aspect of the use case before another, you can enable the
tests separately as development progresses.
When you design the tests, separate the choice of test data from the code or script that determines whether
the postcondition has been achieved. For example, a test of a simple arithmetic function might be: Input 4;
verify that the output is 2. Instead, design the script as: Choose an input; multiply the output by itself, and
verify that the result is the original input. This style enables you to vary the test inputs without changing the
main body of the test.
Linking tests to use cases
If you are using Test Manager to design and run your tests, you can organize your tests under requirement, use
case, or user story work items. You can link these work items to use cases in your model. This enables you to
quickly trace requirements changes to the tests, and helps you track the progress of each use case.
To l i n k t e s t s t o a u s e c a s e

1. In Test Manager, create a requirement and base a test suite on it.


The requirement that you create is a work item in Team Foundation Server. It might be a User Story,
Requirement, or Use Case work item, depending on the process template that your project uses with Team
Foundation. For more information, see Track work using Visual Studio Team Services or Team Foundation
Server.
2. Link the requirement work item to one or more use cases in your model.
In a use case diagram, right-click a use case and then click Link to Work Item.
3. Add to the test suite, test cases that verify the use cases.
Usually, each user story or requirement work item will link to several use cases in your model, and each use
case will link to several user stories or requirements. This is because each user story or requirement covers
a set of tasks that develop several use cases. For example, in an early iteration of your project, you might
develop the basic user story in which a customer can choose items from a catalog and have them delivered.
In a later iteration, the story might be that the user pays when completing the order, and the supplier
receives the money after it sends the goods. Each story adds a clause to the postcondition of the Order
Goods use case.
You can create separate links from requirements to the clauses of the postcondition by writing those
clauses in separate comments on the use case diagram. You can link each comment to a requirement work
item, and link the comment to the use case on the diagram.
Base Tests on the Requirements Types
The types, that is, the classes, interfaces and enumerations, of a requirements model describe the concepts and
relationships in terms of how users think and communicate about their business. It excludes types concerned only
with the internal design of the system.
Design your tests in terms of these requirements types. This practice helps you ensure that when changes to the
requirements are discussed, it is easy to relate the changes to the necessary changes in the tests. It makes it
possible to discuss the tests and their intended results directly with end-users and other stakeholders. This means
that the users' needs can be maintained outside the development process, and avoids the inadvertent design of
the tests around possible flaws in the design.
For manual tests, this practice involves adhering to the vocabulary of the requirements model in the test scripts.
For automated tests, this practice involves using the requirements class diagrams as a basis for your test code, and
creating accessor and updater functions to link the requirement model to the code.
For example, a requirements model might include types Menu, Menu Item, Order, and associations between them.
This model represents the information that is stored and dealt with by the meal ordering system, but does not
represent the complexities of its implementation. In the working system, there might be several different
realizations of each type, in databases, in user interfaces and on APIs. In a distributed system, there might be
several variants of each instance stored in different parts of the system at the same time.
To test a use case such as Add Item to Order, a test method could include code similar to this:

Order order = ... ; // set up an order


// Store prior state:
int countBefore = order.MenuItems.Count;
// Perform use case:
MenuItem chosenItem = ...; // choose an item
AddItemToOrder (chosenItem, order);
// Verify part of postcondition:
int countAfter = order.MenuItems.Count;
Assert (countAfter == countBefore = 1);

Notice that this test method uses the classes of the requirements model. Associations and attributes are realized as
.NET properties.
To make this work, the properties of the classes must be defined as read-only functions or accessors, which access
the system to retrieve information about its current state. Methods that simulate use cases such as
AddItemToOrder must drive the system through its API or through a layer underneath its user interface. The
constructors of test objects such as Order and MenuItem must also drive the system to create corresponding
items inside the system.
Many of the accessors and updaters will already be available through the application's normal API. But some
additional functions might have to be written in order to enable the tests. These additional accessors and updaters
are sometimes known as 'test instrumentation'. Because they depend on the internal design of the system, it is the
responsibility of the system's developers to provide them, whereas the testers write the code of the tests in terms
of the requirements model.
When you write automated tests, you can use Generic Tests to wrap the accessors and updaters.
Tests for Business Rules
Some requirements are not directly related to any one use case. For example, the DinnerNow business allows
customers to choose from many Menus, but requires that in every Order, all the chosen Items shall be from a
single Menu. This business rule can be expressed as an invariant about the associations between Orders, Menus,
and Items in the requirements class model.
An invariant rule of this kind governs not only all the use cases that are currently defined, but also any other use
cases that will be defined later. Therefore, it is useful to write it separately from any use case, and to test it
separately from the use cases.

Deriving Subsystem Tests from Models


In the high-level design of a large system, you can identify components or subsystems. These represent parts that
can be separately designed, or are located on different computers, or are reusable modules that can be
recombined in many ways.
You can apply to each major component the same principles as you use for the complete system. In a large
project, each component can have its own requirements model. In smaller projects, an architectural model or high-
level design can be created to show the major components and their interactions. For more information, see
Model your app's architecture.
In either case, you can establish a relationship between the model elements and the subsystem tests in the same
manner as you would between the requirements model and the system tests.
Isolate Components with Provided and Required Interfaces
It is useful to identify all the dependencies that a component has on other parts of your system or external
services, and to represent these as Required Interfaces. This exercise usually leads to some redesign that leaves the
component much more decoupled and easily separable from the rest of your design.
An advantage of this decoupling is that the component can be executed for testing by replacing with mock objects
the services it usually uses. These are components that are set up for the purposes of testing. A mock component
provides the interface that your component requires, responding to queries with simulated data. The mock
components form part of a complete test harness that you can connect to all the interfaces of the component.
A benefit of mock testing is that you can develop your component while the other components whose services it
will use are still under development.

Maintain the Relationships between Tests and Model


In a typical project that performs an iteration every few weeks, a requirements review is held near the beginning of
each iteration. The meeting discusses the features that are to be delivered in the next iteration. A requirements
model can be used to help discuss the concepts, scenarios, and sequences of actions that will be developed. The
business stakeholders set priorities, the developers make estimates, and the testers ensure the expected behavior
of each feature is captured correctly.
Writing tests is the most effective way to define a requirement, and is also an effective way to ensure that a person
has a clear understanding of what is required. However, whereas writing tests takes too long to do during a
specification workshop, creating models can be done much more rapidly.
From a testing point of view, a requirements model can be seen as a shorthand for the tests. Therefore, it's
important to maintain the relationship between tests and model throughout the project.

Attaching Test Cases to Model Elements


If your project uses Test Manager, you can link tests to the elements in your model. This lets you quickly find the
tests affected by a change in the requirements, and helps you track the extent to which a requirement has been
realized.
You can link tests to all kinds of element. Here are some examples:
Link a use case to the tests that exercise it.
Write the clauses of a use case postcondition, or goal, onto comments that are linked to the use case, and
then link tests to each comment.
Write invariant rules in comments on class diagrams or activity diagrams, and link them to tests.
Link tests to an activity diagram, or to individual activities.
Link a test suite to the component or subsystem it tests.
To link tests to a model element or relationship
1. In Test Manager, create a requirement and base a test suite on it.
The requirement that you create is a work item in Team Foundation Server. It might be a User Story,
Requirement, or Use Case work item, depending on the process template that your project uses with Team
Foundation. For more information, see Track work using Visual Studio Team Services or Team Foundation
Server.
2. Link the requirement work item to one or more elements in your model.
In a modeling diagram, right-click an element, comment or relationship and then click Link to Work Item.
3. Add to the test suite, test cases that verify the requirement expressed in the model element.

See Also
Create models for your app
Model user requirements
Model your app's architecture
Analyzing and Modeling Architecture
Validate code with dependency diagrams
10/18/2017 11 min to read Edit Online

Latest news: See this blog post.


Video: Validate your architecture dependencies in real time

Why use dependency diagrams?


To make sure that code doesn't conflict with its design, validate your code with dependency diagrams in Visual
Studio. This can help you:
Find conflicts between dependencies in your code and dependencies on the dependency diagram.
Find dependencies that might be affected by proposed changes.
For example, you can edit the dependency diagram to show potential architecture changes and then
validate the code to see the affected dependencies.
Refactor or migrate code to a different design.
Find code or dependencies that require work when you move the code to a different architecture.
Requirements
Visual Studio
Visual Studio on your Team Foundation Build server to validate code automatically with Team
Foundation Build
A solution that has a modeling project with a dependency diagram. This dependency diagram must be
linked to artifacts in Visual C# .NET or Visual Basic .NET projects that you want to validate. See Create
dependency diagrams from your code.
To see which versions of Visual Studio support this feature, see Version support for architecture and
modeling tools.
You can validate code manually from an open dependency diagram in Visual Studio or from a command
prompt. You can also validate code automatically when running local builds or Team Foundation Build.
See Channel 9 Video: Design and validate your architecture using dependency diagrams.

IMPORTANT
If you want to run layer validation with Team Foundation Build, you must also install the same version of Visual Studio on
your build server.

See if an item supports validation


Include other .NET assemblies and projects for validation
Validate code manually
Validate code automatically
Troubleshoot layer validation issues
Understand and resolve layer validation errors

Live dependency validation


In this release of Visual Studio, dependency validation occurs in real time, and errors are shown immediately in
the Visual Studio Error List window.
Live validation is supported for C# and Visual Basic.NET.
To enable full solution analysis when using live dependency validation, open the options settings from
the gold bar that appears in the Error List.
You can permanently dismiss this gold bar if you are not interested in seeing all the architectural
issues in your solution.
If you don't enable full solution analysis, the analysis is done only for the files being edited.
When upgrading projects to enable live validation, a dialog shows the progress of the conversion.
When updating a project for live dependency validation, the version of the NuGet package is upgraded to
be the same for all projects, and is the highest version in use.
Adding a new dependency validation project triggers a project update.

See if an item supports validation


You can link layers to Web sites, Office documents, plain text files, and files in projects that are shared across
multiple apps, but the validation process won't include them. Validation errors won't appear for references to
projects or assemblies that are linked to separate layers when no dependencies appear between those layers.
Such references are not considered dependencies unless the code uses those references.
1. On the dependency diagram, select one or more layers, right-click your selection, and then click View
Links.
2. In Layer Explorer, look at the Supports Validation column. If the value is false, the item does not
support validation.

Include other .NET assemblies and projects for validation


When you drag items to the dependency diagram, references to the corresponding .NET assemblies or projects
are added automatically to the Layer References folder in the modeling project. This folder contains references
to the assemblies and projects that are analyzed during validation. You can include other .NET assemblies and
projects for validation without manually dragging them to the dependency diagram.
1. In Solution Explorer, right-click the modeling project or the Layer References folder, and then click
Add Reference.
2. In the Add Reference dialog box, select the assemblies or projects, and then click OK.

Validate code manually


If you have an open dependency diagram that is linked to solution items, you can run the Validate shortcut
command from the diagram. You can also use the command prompt to run the msbuild command with the
/p:ValidateArchitecture custom property set to True. For example, as you make changes in the code, perform
layer validation regularly so that you can catch dependency conflicts early.
To validate code from an open dependency diagram
1. Right-click the diagram surface, and then click Validate Architecture.
NOTE
By default, the Build Action property on the dependency diagram (.layerdiagram) file is set to Validate so that
the diagram is included in the validation process.

The Error List window reports any errors that occur. For more information about validation errors, see
Understand and resolve layer validation errors.
2. To view the source of each error, double-click the error in the Error List window.

NOTE
Visual Studio might show a code map instead of the source of the error. This occurs when either the code has a
dependency on an assembly that is not specified by the dependency diagram, or the code is missing a
dependency that is specified by the dependency diagram. Review the code map or the code to determine whether
the dependency should exist. For more information about code maps, see Map dependencies across your
solutions.

3. To manage errors, see Manage validation errors.


To validate code at the command prompt
1. Open the Visual Studio command prompt.
2. Choose one of the following:
To validate code against a specific modeling project in the solution, run MSBuild with the following
custom property.

msbuild <FilePath+ModelProjectFileName>.modelproj /p:ValidateArchitecture=true

or -
Browse to the folder that contains the modeling project (.modelproj) file and the
dependency diagram and then run MSBuild with the following custom property:

msbuild /p:ValidateArchitecture=true

To validate code against all modeling projects in the solution, run MSBuild with the following
custom property:

msbuild <FilePath+SolutionName>.sln /p:ValidateArchitecture=true

or -
Browse to the solution folder, which must contain a modeling project that contains a
dependency diagram, and then run MSBuild with the following custom property:

msbuild /p:ValidateArchitecture=true

Any errors that occur will be listed. For more information about MSBuild, see MSBuild and
MSBuild Task.
For more information about validation errors, see Understand and resolve layer validation errors.
Manage validation errors
During the development process, you might want to suppress some of the reported conflicts during validation.
For example, you might want to suppress errors that you are already addressing or that are not relevant to your
particular scenario. When you suppress an error, it is a good practice to log a work item in Team Foundation.

WARNING
You must already be connected to TFS Source Code Control (SCC) to create or link to a work item. If you try to open a
connection to a different TFS SCC, Visual Studio closes the current solution automatically. Ensure that you are already
connected to the appropriate SCC before attempting to create or link to a work item. In later releases of Visual Studio, the
menu commands are not available if you are not connected to an SCC.

To c r e a t e a w o r k i t e m fo r a v a l i d a t i o n e r r o r

In the Error List window, right-click the error, point to Create Work Item, and then click the type of work
item that you want to create.
Use these tasks to manage validation errors in the Error List window:

TO FOLLOW THESE STEPS

Suppress selected errors during validation Right-click the one or multiple selected errors, point to
Manage Validation Errors, and then click Suppress Errors.

The suppressed errors appear with strikethrough formatting.


When you run validation the next time, these errors will not
appear.

Suppressed errors are tracked in a .suppressions file for the


corresponding dependency diagram file.

Stop suppressing selected errors Right-click the selected suppressed error or errors, point to
Manage Validation Errors, and then click Stop
Suppressing Errors.

The selected suppressed errors will appear when you run


validation the next time.

Restore all suppressed errors in the Error List window Right-click anywhere in the Error List window, point to
Manage Validation Errors, and then click Show All
Suppressed Errors.

Hide all suppressed errors from the Error List window Right-click anywhere in the Error List window, point to
Manage Validation Errors, and then click Hide All
Suppressed Errors.

Validate code automatically


You can perform layer validation every time that you run a local build. If your team uses Team Foundation Build,
you can perform layer validation with gated check-ins, which you can specify by creating a custom MSBuild task,
and use build reports to collect validation errors. To create gated check-in builds, see Use a gated check-in build
process to validate changes.
To validate code automatically during a local build
Use a text editor to open the modeling project (.modelproj) file, and then include the following property:

<ValidateArchitecture>true</ValidateArchitecture>
- or -
1. In Solution Explorer, right-click the modeling project that contains the dependency diagram or
diagrams, and then click Properties.
2. In the Properties window, set the modeling project's Validate Architecture property to True.
This includes the modeling project in the validation process.
3. In Solution Explorer, click the dependency diagram (.layerdiagram) file that you want to use for
validation.
4. In the Properties window, make sure that the diagram's Build Action property is set to Validate.
This includes the dependency diagram in the validation process.
To manage errors in the Error List window, see Manage Validation Errors.
To validate code automatically during a Team Foundation Build
1. In Team Explorer, double-click the build definition, and then click Process.
2. Under Build process parameters, expand Compilation, and type the following in the MSBuild
Arguments parameter:
/p:ValidateArchitecture=true

For more information about validation errors, see Understand and resolve layer validation errors. For
more information about Team Foundation Build, see:
Build the application
Use the Default Template for your build process
Modify a Legacy Build that is Based on UpgradeTemplate.xaml
Customize your build process template
Monitor Progress of a Running Build

Troubleshoot layer validation issues


The following table describes layer validation issues and their resolution. These issues differ from errors that
result from conflicts between the code and the design. For more information about these errors, see Understand
and resolve layer validation errors.

ISSUE POSSIBLE CAUSE RESOLUTION

Validation errors do not occur as Validation does not work on Add a new dependency diagram to the
expected. dependency diagrams that are copied modeling project.
from other dependency diagrams in
Solution Explorer and that are in the Copy the elements from the source
same modeling project. dependency dependency diagram to the new
diagrams that are copied in this way diagram.
contain the same references as the
original dependency diagram.

Understanding and Resolving Layer Validation Errors


When you validate code against a dependency diagram, validation errors occur when the code conflicts with the
design. For example, the following conditions might cause validation errors to occur:
An artifact is assigned to the wrong layer. In this case, move the artifact.
An artifact, such as a class, uses another class in a way that conflicts with your architecture. In this case,
refactor the code to remove the dependency.
To resolve these errors, update the code until no more errors appear during validation. You can perform
this task in an iterative manner.
The following section describes the syntax that is used in these errors, explains the meaning of these
errors, and suggests what you can do to resolve or manage them.

SYNTAX DESCRIPTION

ArtifactN(ArtifactTypeN) ArtifactN is an artifact that is associated with a layer on the


dependency diagram.

ArtifactTypeN is the type of ArtifactN, such as a Class or


Method, for example:

MySolution.MyProject.MyClass.MyMethod(Method)

NamespaceNameN The name of a namespace.

LayerNameN The name of a layer on the dependency diagram.

DependencyType The type of dependency relationship between Artifact1 and


Artifact2. For example, Artifact1 has a Calls relationship with
Artifact2.

ERROR SYNTAX ERROR DESCRIPTION

DV0001: Invalid Dependency This issue is reported when a code element (namespace,
type, member) mapped to a Layer references a code element
mapped to another layer, but there is no dependency arrow
between these layers in the dependency validation diagram
containing this layers. This is a dependency constraint
violation.

DV1001: Invalid namespace name This issue is reported on a code element associated with a
layer which "Allowed Namespace Names" property does not
contain the namespace in which this code element is defined.
This is a naming constraint violation. Note that the syntax of
"Allowed Namespace Names" is to be a semi-colon list of
namespaces in which code elements associated with are
layer are permitted to be defined.

DV1002: Dependency on unreferenceable namespace This issue is reported on a code element associated with a
layer and referencing another code element defined in a
namespace which is defined in the "Unreferenceable
Namespace" property of the layer. This is a naming
constraint violation. Note that the "Unreferenceable
Namespaces" property is defined as a Semi-colon separated
list of namespaces that should not be referenced in code
elements associated with this layer.
ERROR SYNTAX ERROR DESCRIPTION

DV1003: Disallowed namespace name This issue is reported on a code element associated with a
layer which "Disallowed Namespace Names" property
contains the namespace in which this code element is
defined. This is a naming constraint violation. Note that the
"Disallowed namespace name" property is defined as a Semi-
colon separated list of namespaces in which code elements
associated with this Layer should not be defined.

DV3001: Missing Link Layer 'LayerName' links to 'Artifact' which cannot be found.
Are you missing an assembly reference?

DV9001: Architectural analysis found internal errors Results might not be complete. For more information, see
the detailed build event log or output window.

See Also
Validate your system during development
Video: Validate your architecture dependencies in real time
Extend dependency diagrams
11/7/2017 1 min to read Edit Online

You can write code to create and update dependency diagrams, and to validate the structure of your program code
against dependency diagrams in Visual Studio. You can add commands that appear in the shortcut (context) menu
of the diagrams, customize drag-and-drop gestures, and access the layer model from text templates. You can
package these extensions into a Visual Studio Integration Extension (VSIX) and distribute them to other Visual
Studio users.
For more information about dependency diagrams, see:
Dependency Diagrams: Reference
Dependency Diagrams: Guidelines
Create dependency diagrams from your code
Validate code with dependency diagrams

Requirements
You must have the following installed on the computer where you want to develop your layer extensions:
Visual Studio
Visual Studio SDK
Modeling SDK for Visual Studio

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.

You must have a suitable version of Visual Studio installed on the computer where you want to run your layer
extensions. For more information, see Deploy a layer model extension.
To see which versions of Visual Studio support dependency diagrams, see Version support for architecture and
modeling tools.

In This Section
Add commands and gestures to dependency diagrams
Add custom architecture validation to dependency diagrams
Add custom properties to dependency diagrams
Navigate and update layer models in program code
Deploy a layer model extension
Troubleshoot extensions for dependency diagrams

See Also
Dependency Diagrams: Reference
Dependency Diagrams: Guidelines
Create dependency diagrams from your code
Validate code with dependency diagrams
Add commands and gestures to dependency
diagrams
11/7/2017 6 min to read Edit Online

You can define context menu commands and gesture handlers on dependency diagrams in Visual Studio. You can
package these extensions into a Visual Studio Integration Extension (VSIX) that you can distribute to other Visual
Studio users.
You can define several command and gesture handlers in the same Visual Studio project if you want. You can also
combine several such projects into one VSIX. For example, you could define a single VSIX that includes layer
commands, and a domain-specific language.

NOTE
You can also customize architecture validation, in which users' source code is compared with dependency diagrams. You
should define architecture validation in a separate Visual Studio project. You can add it to the same VSIX as other extensions.
For more information, see Add custom architecture validation to dependency diagrams.

Requirements
See Requirements.

Defining a Command or Gesture in a New VSIX


The quickest method of creating an extension is to use the project template. This places the code and the VSIX
manifest into the same project.
To define an extension by using a project template
1. Create a project in a new solution, by using the New Project command on the File menu.
2. In the New Project dialog box, under Modeling Projects, select either Layer Designer Command
Extension or Layer Designer Gesture Extension.
The template creates a project that contains a small working example.
3. To test the extension, press CTRL+F5 or F5.
An experimental instance of Visual Studio starts. In this instance, create a dependency diagram. Your
command or gesture extension should work in this diagram.
4. Close the experimental instance and modify the sample code. For more information, see Navigate and
update layer models in program code.
5. You can add more command or gesture handlers to the same project. For more information, see one of the
following sections:
Defining a Menu Command
Defining a Gesture Handler
6. To install the extension in the main instance of Visual Studio, or on another computer, find the .vsix file in
bin\\. Copy it to the computer where you want to install it, and then double-click it. To uninstall it, use
**Extensions and Updates* on the Tools menu.
Adding a Command or Gesture to a separate VSIX
If you want to create one VSIX that contains commands, layer validators, and other extensions, we recommend that
you create one project to define the VSIX, and separate projects for the handlers.
To add layer extensions to a separate VSIX
1. Create a Class Library project in a new or existing Visual Studio solution. In the New Project dialog box,
click Visual C# and then click Class Library. This project will contain command or gesture handler classes.

NOTE
You can define more than one command or gesture handler class in one class library, but you should define layer
validation classes in a separate class library.

2. Identify or create a VSIX project in your solution. A VSIX project contains a file that is named
source.extension.vsixmanifest. To add a VSIX project:
a. In the New Project dialog box, expand Visual C#, then click Extensibility, and then click VSIX
Project.
b. In Solution Explorer, right-click the VSIX project and then click Set as Startup Project.
c. Click Select Editions and make sure that Visual Studio is checked.
3. In source.extension.vsixmanifest, under Assets, add the command or gesture handler project as a MEF
component.
a. In the Assets.tab, choose New.
b. At Type, select Microsoft.VisualStudio.MefComponent.
c. At Source, select Project in current solution and select the name of your command or gesture
handler project.
d. Save the file.
4. Return to the command or gesture handler project, and add the following project references.

REFERENCE WHAT THIS ALLOWS YOU TO DO

Program Files\Microsoft Visual Studio Create and edit layers


[version]\Common7\IDE\Extensions\Microsoft\Architecture
Tools\ExtensibilityRuntime\Microsoft.VisualStudio.Architecture
Tools.Extensibility.Layer.dll

Microsoft.VisualStudio.Uml.Interfaces Create and edit layers

Microsoft.VisualStudio.ArchitectureTools.Extensibility Modify shapes on diagrams

System.ComponentModel.Composition Define components using Managed Extensibility Framework


(MEF)

Microsoft.VisualStudio.Modeling.Sdk.[version] Define modeling extensions

Microsoft.VisualStudio.Modeling.Sdk.Diagrams.[version] Update shapes and diagrams

1. Edit the class file in the C# class library project to contain the code for your extension. For more information,
see one of the following sections:
Defining a Menu Command
Defining a Gesture Handler
See also Navigate and update layer models in program code.
2. To test the feature, press CTRL+F5 or F5. An experimental instance of Visual Studio opens. In this instance,
create or open a dependency diagram.
3. To install the VSIX in the main instance of Visual Studio, or on another computer, find the .vsix file in the
bin directory of the VSIX project. Copy it to the computer where you want to install the VSIX. Double-click
the VSIX file in Windows Explorer (File Explorer in Windows 8).
To uninstall it, use Extensions and Updates on the Tools menu.

Defining a Menu Command


You can add more menu command definitions to an existing gesture or command project. Each command is
defined by a class that has the following characteristics:
The class is declared as follows:
[LayerDesignerExtension]

[Export(typeof(ICommandExtension))]

public class MyLayerCommand : ICommandExtension { ... }

The namespace and the name of the class are unimportant.


The methods that implement ICommandExtension are as follows:
string Text {get;} - The label that appears in the menu.
void QueryStatus(IMenuCommand command) - called when the user right-clicks the diagram, and
determines whether the command should be visible and enabled for the user's current selection.
void Execute(IMenuCommand command) - called when the user selects the command.
To determine the current selection, you can import IDiagramContext :
[Import]

public IDiagramContext DiagramContext { get; set; }

...

DiagramContext.CurrentDiagram.SelectedShapes.Count()...

For more information, see Navigate and update layer models in program code.
To add a new command, create a new code file that contains the following sample. Then test and edit it.

using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
using System.ComponentModel.Composition;
using System.Linq;

namespace MyLayerExtension // Change to your preference.


{
// This is a feature for dependency diagrams:
[LayerDesignerExtension]
[LayerDesignerExtension]
// This feature is a menu command:
[Export(typeof(ICommandExtension))]
// Change the class name to your preference:
public class MyLayerCommand : ICommandExtension
{
[Import]
public IDiagramContext DiagramContext { get; set; }

[Import]
public ILinkedUndoContext LinkedUndoContext { get; set; }

// Menu command label:


public string Text
{
get { return "Duplicate layers"; }
}

// Called when the user right-clicks the diagram.


// Defines whether the command is visible and enabled.
public void QueryStatus(IMenuCommand command)
{
command.Visible =
command.Enabled = DiagramContext.CurrentDiagram
.SelectedShapes.Count() > 0;
}

// Called when the user selects the command.


public void Execute(IMenuCommand command)
{
// A selection of starting points:
IDiagram diagram = this.DiagramContext.CurrentDiagram;
ILayerModel lmodel = diagram.GetLayerModel();
foreach (ILayer layer in lmodel.Layers)
{ // All layers in model.
}
// Updates should be performed in a transaction:
using (ILinkedUndoTransaction t =
LinkedUndoContext.BeginTransaction("copy selection"))
{
foreach (ILayer layer in
diagram.SelectedShapes
.Select(shape=>shape.GetLayerElement())
.Where(element => element is ILayer))
{
ILayer copy = lmodel.CreateLayer(layer.Name + "+");
// Position the shapes:
IShape originalShape = layer.GetShape();
copy.GetShape().Move(
originalShape.XPosition + originalShape.Width * 1.2,
originalShape.YPosition);
}
t.Commit();
}
}
}
}

Defining a Gesture Handler


A gesture handler responds when the user drags items onto the dependency diagram, and when the user double-
clicks anywhere in the diagram.
To your existing command or gesture handler VSIX project, you can add a code file that defines a gesture handler:
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
using System.ComponentModel.Composition;
using System.Linq;
namespace MyLayerExtensions // change to your preference
{
[LayerDesignerExtension]
[Export(typeof(IGestureExtension))]
public class MyLayerGestureHandler : IGestureExtension
{
}
}

Notice the following points about gesture handlers:


The members of IGestureExtension are as follows:
OnDoubleClick - called when the user double-clicks anywhere on the diagram.
CanDragDrop - called repeatedly as the user moves the mouse while dragging an item onto the diagram. It
must work quickly.
OnDragDrop - called when the user drops an item onto the diagram.
The first argument to each method is an IShape , from which you can get the layer element. For example:

public void OnDragDrop(IShape target, IDataObject data)


{
ILayerElement element = target.GetLayerElement();
if (element is ILayer)
{
// ...
}
}

Handlers for some types of dragged item are already defined. For example, the user can drag items from
Solution Explorer onto a dependency diagram. You cannot define a drag handler for these types of item. In
these cases, your DragDrop methods will not be invoked.

See Also
Navigate and update layer models in program code
Add custom architecture validation to dependency diagrams
Add custom architecture validation to dependency
diagrams
10/18/2017 8 min to read Edit Online

In Visual Studio, users can validate the source code in a project against a layer model so that they can verify that
the source code conforms to the dependencies on a dependency diagram. There is a standard validation
algorithm, but you can define your own validation extensions.
When the user selects the Validate Architecture command on a dependency diagram, the standard validation
method is invoked, followed by any validation extensions that have been installed.

NOTE
In a dependency diagram, the main purpose of validation is to compare the diagram with the program code in other parts
of the solution.

You can package your layer validation extension into a Visual Studio Integration Extension (VSIX), which you can
distribute to other Visual Studio users. You can either place your validator in a VSIX by itself, or you can combine it
in the same VSIX as other extensions. You should write the code of the validator in its own Visual Studio project,
not in the same project as other extensions.

WARNING
After you have created a validation project, copy the example code at the end of this topic and then edit that to your own
needs.

Requirements
See Requirements.

Defining a Layer Validator in a New VSIX


The quickest method of creating a validator is to use the project template. This places the code and the VSIX
manifest into the same project.
To define an extension by using a project template
1. Create a project in a new solution, by using the New Project command on the File menu.
2. In the New Project dialog box, under Modeling Projects, select Layer Designer Validation Extension.
The template creates a project that contains a small example.
WARNING
To makethe template work properly:
Edit calls to LogValidationError to remove the optional arguments errorSourceNodes and
errorTargetNodes .
If you use custom properties, apply the update mentioned in Add custom properties to dependency
diagrams.

3. Edit the code to define your validation. For more information, see Programming Validation.
4. To test the extension, see Debugging Layer Validation.

NOTE
Your method will be called only in specific circumstances, and breakpoints will not work automatically. For more
information, see Debugging Layer Validation.

5. To install the extension in the main instance of Visual Studio, or on another computer, find the .vsix file in
bin\\. Copy it to the computer where you want to install it, and then double-click it. To uninstall it, use
**Extensions and Updates* on the Tools menu.

Adding a Layer Validator to a Separate VSIX


If you want to create one VSIX that contains layer validators, commands, and other extensions, we recommend
that you create one project to define the VSIX, and separate projects for the handlers.
To add layer validation to a separate VSIX
1. Create a Class Library project in a new or existing Visual Studio solution. In the New Project dialog box,
click Visual C# and then click Class Library. This project will contain the layer validation class.
2. Identify or create a VSIX project in your solution. A VSIX project contains a file that is named
source.extension.vsixmanifest. If you have to add a VSIX project, follow these steps:
a. In the New Project dialog box, choose Visual C#, Extensibility, VSIX Project.
b. In Solution Explorer, on the shortcut menu of the VSIX project, Set as Startup Project.
3. In source.extension.vsixmanifest, under Assets, add the layer validation project as a MEF component:
a. Choose New.
b. In the Add New Asset dialog box, set:
Type = Microsoft.VisualStudio.MefComponent
Source = A project in current solution
Project = your validator project
4. You must also add it as a layer validation:
a. Choose New.
b. In the Add New Asset dialog box, set:
Type = Microsoft.VisualStudio.ArchitectureTools.Layer.Validator. This is not one of the
options in the drop-down list. You must enter it from the keyboard.
Source = A project in current solution
Project = your validator project
5. Return to the layer validation project, and add the following project references:

REFERENCE WHAT THIS ALLOWS YOU TO DO

Microsoft.VisualStudio.GraphModel.dll Read the architecture graph

Microsoft.VisualStudio.ArchitectureTools.Extensibility.Code Read the code DOM associated with layers


Schema.dll

Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer Read the Layer model


.dll

Microsoft.VisualStudio.ArchitectureTools.Extensibility Read and update shapes and diagrams.

System.ComponentModel.Composition Define the validation component using Managed


Extensibility Framework (MEF)

Microsoft.VisualStudio.Modeling.Sdk.[version] Define modeling extensions

6. Copy the example code at the end of this topic into the class file in the validator library project to contain
the code for your validation. For more information, see Programming Validation.
7. To test the extension, see Debugging Layer Validation.

NOTE
Your method will be called only in specific circumstances, and breakpoints will not work automatically. For more
information, see Debugging Layer Validation.

8. To install the VSIX in the main instance of Visual Studio, or on another computer, find the .vsix file in the
bin directory of the VSIX project. Copy it to the computer where you want to install the VSIX. Double-click
the VSIX file in Windows Explorer. (File Explorer in Windows 8.)
To uninstall it, use Extensions and Updates on the Tools menu.

Programming Validation
To define a layer validation extension, you define a class that has the following characteristics:
The overall form of the declaration is as follows:
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
using Microsoft.VisualStudio.GraphModel;
...
[Export(typeof(IValidateArchitectureExtension))]
public partial class Validator1Extension :
IValidateArchitectureExtension
{
public void ValidateArchitecture(Graph graph)
{
GraphSchema schema = graph.DocumentSchema;
...
} }

When you discover an error, you can report it by using LogValidationError() .

WARNING
Do not use the optional parameters of LogValidationError .

When the user invokes the Validate Architecture menu command, the layer runtime system analyses the
layers and their artifacts to produce a graph. The graph has four parts:
The layer models of the Visual Studio solution that are represented as nodes and links in the graph.
The code, project items, and other artifacts that are defined in the solution and represented as nodes, and
links that represent the dependencies discovered by the analysis process.
Links from the layer nodes to the code artifact nodes.
Nodes that represent errors discovered by the validator.
When the graph has been constructed, the standard validation method is called. When this is complete, any
installed extension validation methods are called in unspecified order. The graph is passed to each
ValidateArchitecture method, which can scan the graph and report any errors that it finds.

NOTE
This is not the same as the validation process that can be used in domain-specific languages.

Validation methods should not change the layer model or the code that is being validated.
The graph model is defined in Microsoft.VisualStudio.GraphModel. Its principal classes are GraphNode and
GraphLink.
Each Node and each Link has one or more Categories which specify the type of element or relationship that it
represents. The nodes of a typical graph have the following categories:
Dsl.LayerModel
Dsl.Layer
Dsl.Reference
CodeSchema_Type
CodeSchema_Namespace
CodeSchema_Type
CodeSchema_Method
CodeSchema_Field
CodeSchema_Property
Links from layers to elements in the code have the category "Represents".

Debugging Validation
To debug your layer validation extension, press CTRL+F5. An experimental instance of Visual Studio opens. In this
instance, open or create a layer model. This model must be associated with code, and must have at least one
dependency.
Test with a Solution that contains Dependencies
Validation is not executed unless the following characteristics are present:
There is at least one dependency link on the dependency diagram.
There are layers in the model that are associated with code elements.
The first time that you start an experimental instance of Visual Studio to test your validation extension,
open or create a solution that has these characteristics.
Run Clean Solution before Validate Architecture
Whenever you update your validation code, use the Clean Solution command on the Build menu in the
experimental solution, before you test the Validate command. This is necessary because the results of validation
are cached. If you have not updated the test dependency diagram or its code, the validation methods will not be
executed.
Launch the Debugger Explicitly
Validation runs in a separate process. Therefore, the breakpoints in your validation method will not be triggered.
You must attach the debugger to the process explicitly when validation has started.
To attach the debugger to the validation process, insert a call to System.Diagnostics.Debugger.Launch() at the start
of your validation method. When the debugging dialog box appears, select the main instance of Visual Studio.
Alternatively, you can insert a call to System.Windows.Forms.MessageBox.Show() . When the message box appears, go
to the main instance of Visual Studio and on the Debug menu click Attach to Process. Select the process that is
named Graphcmd.exe.
Always start the experimental instance by pressing CTRL+F5 (Start without Debugging).
Deploying a Validation Extension
To install your validation extension on a computer on which a suitable version of Visual Studio is installed, open
the VSIX file on the target computer. To install on a computer on which Team Foundation Build is installed, you
must manually extract the VSIX contents into an Extensions folder. For more information, see Deploy a layer
model extension.

Example code
using System;
using System.ComponentModel.Composition;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
using Microsoft.VisualStudio.GraphModel;

namespace Validator3
{
[Export(typeof(IValidateArchitectureExtension))]
public partial class Validator3Extension : IValidateArchitectureExtension
{
/// <summary>
/// Validate the architecture
/// </summary>
/// <param name="graph">The graph</param>
public void ValidateArchitecture(Graph graph)
{
if (graph == null) throw new ArgumentNullException("graph");

// Uncomment the line below to debug this extension during validation


// System.Windows.Forms.MessageBox.Show("Attach 2 to GraphCmd.exe with process id " +
System.Diagnostics.Process.GetCurrentProcess().Id);

// Get all layers on the diagram


foreach (GraphNode layer in graph.Nodes.GetByCategory("Dsl.Layer"))
{
System.Threading.Thread.Sleep(100);
// Get the required regex property from the layer node
string regexPattern = "^[a-zA-Z]+$"; //layer[customPropertyCategory] as string;
if (!string.IsNullOrEmpty(regexPattern))
{
Regex regEx = new Regex(regexPattern);

// Get all referenced types in this layer including those from nested layers so each
// type is validated against all containing layer constraints.
foreach (GraphNode containedType in layer.FindDescendants().Where(node =>
node.HasCategory("CodeSchema_Type")))
{
// Check the type name against the required regex
CodeGraphNodeIdBuilder builder = new CodeGraphNodeIdBuilder(containedType.Id, graph);
string typeName = builder.Type.Name;
if (!regEx.IsMatch(typeName))
{
// Log an error
string message = string.Format(CultureInfo.CurrentCulture,
Resources.InvalidTypeNameMessage, typeName);
this.LogValidationError(graph, typeName + "TypeNameError", message,
GraphErrorLevel.Error, layer);
}
}
}

}
}
}

See Also
Extend dependency diagrams
Add custom properties to dependency diagrams
10/18/2017 3 min to read Edit Online

When you write extension code for dependency diagrams, you can store values with any element on a dependency
diagram. The values will persist when the diagram is saved and re-opened. You can also have these properties
appear in the Properties window so that users can see and edit them. For example, you could let users specify a
regular expression for each layer, and write validation code to verify that the names of classes in each layer
conform to the pattern specified by the user.

Properties not visible to the user


If you just want your code to attach values to any element in a dependency diagram, you don't need to define a
MEF component. There is a dictionary named Properties in ILayerElement. Simply add marshalable values to the
dictionary of any layer element. They will be saved as part of the dependency diagram. For more information, see
Navigate and update layer models in program code.

Properties that the user can edit


Initial preparation

IMPORTANT
To make properties appear, you must make the following change on each computer where you want layer properties to be
visible.
1. Run Notepad by using Run as Administrator. Open
%ProgramFiles%\Microsoft Visual Studio [version]\Common7\IDE\Extensions\Microsoft\Architecture
Tools\ExtensibilityRuntime\extension.vsixmanifest

a. Inside the Content element, add:

<MefComponent>Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer.Provider.dll</MefComponen
t>

a. Under the Visual Studio Tools section of the Visual Studio application start menu, open Developer Command
Prompt.
Enter:
devenv /rootSuffix /updateConfiguration

devenv /rootSuffix Exp /updateConfiguration

a. Restart Visual Studio.

Make sure your code is in a VSIX project


If your property is part of a command, gesture, or validation project, you don't need to add anything. The code for
your custom property should be defined in a Visual Studio Extensibility project defined as a MEF component. For
more information, see Add commands and gestures to dependency diagrams or Add custom architecture
validation to dependency diagrams.
Define the custom property
To create a custom property, define a class like this:
[Export(typeof(IPropertyExtension))]
public class MyProperty
: PropertyExtension<ILayerElement>
{
// Implement the interface.
}

You can define properties on ILayerElement or any of its derived classes, which include:
ILayerModel - the model
ILayer - each layer
ILayerDependencyLink - the links between layers
ILayerComment

ILayerCommentLink

Example
The following code is a typical custom property descriptor. It defines a Boolean property on the layer model (
ILayerModel ) that lets the user provide values for a custom validation method.

using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;

namespace MyNamespace
{
/// <summary>
/// Custom properties are added to the Layer Designer via a custom
/// Property Descriptor. We have to export this Property Descriptor
/// using MEF to make it available in the Layer Designer.
/// </summary>
[Export(typeof(IPropertyExtension))]
public class AllTypesMustBeReferencedProperty
: PropertyExtension<ILayerModel>
{
/// <summary>
/// Each custom property must have a unique name.
/// Usually we use the full name of this class.
/// </summary>
public static readonly string FullName =
typeof(AllTypesMustBeReferencedProperty).FullName;

/// <summary>
/// Construct the property. Notice the use of FullName.
/// </summary>
public AllTypesMustBeReferencedProperty()
: base(FullName)
{ }

/// <summary>
/// The display name is shown in the Properties window.
/// We therefore use a localizable resource.
/// </summary>
public override string DisplayName
{
get { return Strings.AllTypesMustBeReferencedDisplayName; }
}

/// <summary>
/// Description shown at the bottom of the Properties window.
/// We use a resource string for easier localization.
/// </summary>
public override string Description
{
get { return Strings.AllTypesMustBeReferencedDescription; }
}

/// <summary>
/// This is called to set a new value for this property. We must
/// throw an exception if the value is invalid.
/// </summary>
/// <param name="component">The target ILayerElement</param>
/// <param name="value">The new value</param>
public override void SetValue(object component, object value)
{
ValidateValue(value);
base.SetValue(component, value);
}
/// <summary>
/// Helper to validate the value.
/// </summary>
/// <param name="value">The value to validate</param>
private static void ValidateValue(object value)
{ }

public override Type PropertyType


{ get { return typeof(bool); } }

/// <summary>
/// The segment label of the properties window.
/// </summary>
public override string Category
{
get
{
return Strings.AllTypesMustBeReferencedCategory;
}
}
}
}

See Also
Extend dependency diagrams
Navigate and update layer models in program code
11/7/2017 3 min to read Edit Online

This topic describes the elements and relationships in layer models, which you can navigate and update by using
program code. For more information about dependency diagrams from the user's point of view, see Dependency
Diagrams: Reference and Dependency Diagrams: Guidelines.
The Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer model described in this topic is a facade on a
more general Microsoft.VisualStudio.GraphModel model. If you are writing a menu command or gesture
extension, use the Layer model. If you are writing a layer validation extension, it is easier to use the GraphModel .

Transactions
When you update a model, consider enclosing the changes in a ILinkedUndoTransaction . This groups your
changes into one transaction. If any of the changes fails, the whole transaction will be rolled back. If the user
undoes a change, all the changes will be undone together.

using (ILinkedUndoTransaction t =
LinkedUndoContext.BeginTransaction("a name"))
{
// Make changes here ....
t.Commit(); // Don't forget this!
}

Containment

Layers (ILayer) and the layer model (ILayerModel) can contain Comments and Layers.
A layer ( ILayer ) can be contained in a layer model ( ILayerModel ) or it can be nested within another ILayer .
To create a comment or a layer, use the creation methods on the appropriate container.

Dependency Links
A dependency link is represented by an object. It can be navigated in either direction:
To create a dependency link, call source.CreateDependencyLink(target) .

Comments
Comments can be contained inside layers or the layer model, and can also be linked to any layer element:

A comment can be linked to any number of elements, including none.


To get the comments that are attached to a layer element, use:

ILayerModel model = diagram.GetLayerModel();


IEnumerable<ILayerComment> comments =
model.Comments.Where(comment =>
comment.Links.Any(link => link.Target == layerElement));

Cau t i on

The Comments property of an ILayer gets comments that are contained within the ILayer . It does not get the
comments that are linked to it.
Create a comment by invoking CreateComment() on the appropriate container.
Create a link by using CreateLink() on the comment.

Layer Elements
All the types of element that can be contained in a model are layer elements:
Properties
Each ILayerElement has a string dictionary named Properties . You can use this dictionary to attach arbitrary
information to any layer element.

Artifact References
An artifact reference (ILayerArtifactReference) represents the link between a layer and a project item such as a file,
class, or folder. The user creates artifacts when they create a layer or add to it by dragging items from Solution
Explorer, Class View, or Object Browser onto a dependency diagram. Any number of artifact references can be
linked to a layer.
Each row in Layer Explorer displays an artifact reference. For more information, see Create dependency diagrams
from your code.
The principal types and methods concerned with artifact references are as follows:
ILayerArtifactReference. The Categories property indicates what kind of artifact is referenced, such as a class,
executable file, or assembly. Categories determines how the Identifier identifies the target artifact.
CreateArtifactReferenceAsync creates an artifact reference from an Project or ProjectItem. This is an asynchronous
operation. Therefore, you usually provide a callback that is called when the creation is complete.
Layer Artifact References should not be confused with Artifacts in use case diagrams.

Shapes and Diagrams


Two objects are used to represent each element in a layer model: an ILayerElement, and an IShape. The IShape
represents the position and size of the shape on the diagram. In layer models, every ILayerElement has one
IShape , and every IShape on a dependency diagram has one ILayerElement . IShape is also used for UML
models. Therefore, not every IShape has a layer element.
In the same manner, the ILayerModel is displayed on one IDiagram.
In the code of a custom command or gesture handler, you can get the current diagram and the current selection
of shapes from the DiagramContext import:
public class ... {
[Import]
public IDiagramContext DiagramContext { get; set; }
...
public void ... (...)
{ IDiagram diagram = this.DiagramContext.CurrentDiagram;
ILayerModel model = diagram.GetLayerModel();
if (model != null)
{ foreach (ILayer layer in model.Layers) { ... }}
foreach (IShape selected in diagram.SelectedShapes)
{ ILayerElement element = selected.GetLayerElement();
if (element != null) ... }}

IShape and IDiagram are also used to display UML models.

See Also
Add commands and gestures to dependency diagrams
Add custom architecture validation to dependency diagrams
Add custom properties to dependency diagrams
Dependency Diagrams: Reference
Dependency Diagrams: Guidelines
Deploy a layer model extension
10/18/2017 1 min to read Edit Online

Other users of Visual Studio can install layer modeling extensions that you create by using Visual Studio.

Installing your extension


Your extension is compiled to a VSIX file, which you can install on other computers. You can also install it on your
development computer, to make the extension available in the main instance of Visual Studio.
To install the extension
1. In the project that contains source.vsix.manifest, open bin\\* in File Explorer.
2. Copy the *.vsix file to the computer on which you want to install the extension.
3. On the target computer, double-click the *.vsix file in Windows Explorer.
The VSIX installer opens.
To uninstall the extension
1. In Visual Studio, on the Tools menu, click Extensions and Updates.
2. Click the name of the extension and then click Uninstall.

Installing an Extension on a Team Foundation Build Server


Team Foundation Build servers do not normally have Visual Studio installed, and so you cannot install the VSIX by
double-clicking it. The installation of Team Foundation Build includes some components that allow a VSIX
extension to run, but you must install the extension manually.
To install your layer extension on a Team Foundation Build Server
1. Copy the .vsix files from your development computer to the Team Foundation Build computer.
Place the VSIX file in one of the following locations:
To install for all users and services:
%ProgramFiles%\Microsoft Visual Studio [version]\Common7\IDE\Extensions\Microsoft
To install only for the network service that runs Team Foundation Build:
%WinDir%\ServiceProfiles\NetworkService\AppData\Local\Microsoft\VisualStudio\
[version]\Extensions\Microsoft
If you have configured Team Foundation Build to run in interactive mode as a particular user, you
can install just for that user:
%LocalAppData%\Microsoft\VisualStudio\[version]\Extensions\Microsoft

NOTE
%LocalAppData% is typically DriveName:UsersUserNameAppDataLocal.

2. Expand each VSIX file into a folder in the same location:


a. Change the file name extension from .vsix to .zip.
b. Extract the content of the .zip file to a folder.
c. Delete the .zip file
3. Restart Team Foundation Build.
Troubleshoot extensions for dependency diagrams
10/18/2017 1 min to read Edit Online

This topic addresses some problems that you might encounter when you create layer model extensions.
When I press F5 to debug my extension, my commands, gesture handlers, validation extensions, or custom properties do not appear
on dependency diagrams in the Experimental instance of Visual Studio
1. Open your extension solution in the Experimental instance of Visual Studio, and on the Build menu, click
Rebuild Solution.
2. Press F5 or CTRL+F5 to start the experimental instance of Visual Studio. Open a dependency diagram and
test your extension.
Continue with the next procedure if necessary.
An old version of my extension runs.
1. Make sure that no experimental instance of Visual Studio is running.
2. Delete the following folder: %LocalAppData%\Microsoft\VisualStudio\[version]\ComponentModelCache

NOTE
%LocalAppData% is typically DriveName:\Users\UserName\AppData\Local.

Continue with the next procedure if necessary.


An old version of my validation results appears, or my validation method is not called.
1. In the experimental instance of Visual Studio, on the Build menu, click Clean Solution. This clears the
cached results of the previous validation analysis.
2. Make sure that the layers in your model are associated with code elements, and that there is at least one
dependency link in the model. Validation is not invoked if there is nothing to validate.
3. Regular breakpoints might not work in a validation method, because it runs in a separate process. You must
insert a call to System.Diagnostics.Debugger.Launch() if you want to step through your method.
4. In source.extension.vsixmanifest in your layer validation project, make sure that you have added both a
MEF Component item and a Custom Extension Type item under Content.

See Also
Extend dependency diagrams
Modeling SDK for Visual Studio - Domain-Specific
Languages
10/18/2017 2 min to read Edit Online

By using the Modeling SDK for Visual Studio, you can create powerful model-based development tools that you
can integrate into Visual Studio. In the same manner, you can create one or more model definitions and integrate
them into a set of tools.
At the heart of MSDK is the definition of a model that you create to represent concepts in your business area. You
can surround the model with a variety of tools, such as a diagrammatic view, the ability to generate code and other
artifacts, commands for transforming the model, and the ability to interact with code and other objects in Visual
Studio. As you develop the model, you can combine it with other models and tools to form a powerful toolset that
is centered on your development.
MSDK lets you develop a model quickly in the form of a domain-specific language (DSL). You begin by using a
specialized editor to define a schema or abstract syntax together with a graphical notation. From this definition,
VMSDK generates:
A model implementation with a strongly-typed API that runs in a transaction-based store.
A tree-based explorer.
A graphical editor in which users can view the model or parts of it that you define.
Serialization methods that save your models in readable XML.
Facilities for generating program code and other artifacts using text templating.
You can customize and extend all of these features. Your extensions are integrated in such a way that you
can still update the DSL definition and re-generate the features without losing your extensions.

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.

Related blog posts


For guidance on advanced techniques and troubleshooting, visit Visual Studio DSL & Modeling Tools Extensibility
forum.

In This Section
Getting Started with Domain-Specific Languages
Understanding Models, Classes and Relationships
How to Define a Domain-Specific Language
Customizing and Extending a Domain-Specific Language
Validation in a Domain-Specific Language
Writing Code to Customise a Domain-Specific Language
Generating Code from a Domain-Specific Language
Understanding the DSL Code
Customizing File Storage and XML Serialization
Deploying Domain-Specific Language Solutions
Creating a Windows Forms-Based Domain-Specific Language
Creating a WPF-Based Domain-Specific Language
How to: Extend the Domain-Specific Language Designer
Supported Visual Studio Editions for Visualization & Modeling SDK
How to: Migrate a Domain-Specific Language to a New Version
API Reference for Modeling SDK for Visual Studio
Getting Started with Domain-Specific Languages
10/18/2017 17 min to read Edit Online

This topic explains the basic concepts in defining and using a domain-specific language (DSL) created with the
Modeling SDK for Visual Studio.

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.

If you are new to DSLs, we recommend that you work through the DSL Tools Lab, which you can find in this site:
Visualizaton and Modeling SDK

What can you do with a Domain-Specific Language?


A domain-specific language is a notation, usually graphical, that is designed to be used for a particular purpose. By
contrast, languages such as UML are general-purpose. In a DSL, you can define the types of model element and
their relationships, and how they are presented on the screen.
When you have designed a DSL, you can distribute it as part of a Visual Studio Integration Extension (VSIX)
package. Users work with the DSL in Visual Studio:

The notation is only part of a DSL. Together with the notation, your VSIX package includes tools that users can
apply to help them edit and generate material from their models.
One of the principal applications of DSLs is to generate program code, configuration files, and other artifacts.
Especially in large projects and product lines, where several variants of a product will be created, generating many
of the variable aspects from DSLs can provide a large increase in reliability and a very rapid response to
requirements changes.
The rest of this overview is a walkthrough that introduces the basic operations of creating and using a domain-
specific language in Visual Studio.

Prerequisites
To define a DSL, you must have installed the following components:

Visual Studio http://go.microsoft.com/fwlink/?LinkId=185579


Visual Studio SDK http://go.microsoft.com/fwlink/?LinkId=185580

Modeling SDK for Visual Studio

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.

Creating a DSL Solution


To create a new domain-specific language, you create a new Visual Studio solution by using the Domain-Specific
Language project template.
To create a DSL solution
1. On the File menu, point to New, and then click Project.
2. Under Project types, expand the Other Project Types node, and click Extensibility.
3. Click Domain-Specific Language Designer.

4. In the Name box, type FamilyTree. Click OK.


The Domain-Specific Language Wizard opens, and displays a list of template DSL solutions.
Click each template to see a description,
The templates are useful starting points. Each of them provides a complete working DSL, which you can edit
to suit your needs. Ordinarily, you would choose the template nearest what you want to create.
5. For this walkthrough, choose the Minimal Language template.
6. Enter a file name extension for your DSL in the appropriate wizard page. This is the extension that files
containing instances of your DSL will use.
Choose an extension that is not associated with any application in your computer, or in any computer
where you want to install the DSL. For example, docx and htm would be unacceptable file name
extensions.
The wizard will warn you if the extension that you have entered is being used as a DSL. Consider
using a different file name extension. You can also reset the Visual Studio SDK Experimental instance
to clear out old experimental designers. Click Start, click All Programs, Microsoft Visual Studio
2010 SDK, Tools, and then Reset the Microsoft Visual Studio 2010 Experimental instance.
7. Inspect the other pages and then click Finish.
A solution is generated that contains two projects. They are named Dsl and DslPackage. A diagram file
opens that is named DslDefinition.dsl.

NOTE
Most of the code that you can see in the folders in the two projects is generated from DslDefinition.dsl. For this
reason, most modifications to your DSL are made in this file.

The user interface now resembles the following picture.

This solution defines a domain specific language. For more information, see Overview of the Domain-
Specific Language Tools User Interface.

The important parts of the DSL solution


Notice the following aspects of the new solution.
Dsl\DslDefinition.dsl This is the file that you see when you create a DSL solution. Almost all the code in
the solution is generated from this file, and most of the changes that you make to a DSL definition are made
here. For more information, see Working with the Working with the DSL Definition Diagram.
Dsl project This project contains code that defines the domain-specific language.
DslPackage project This project contains code that allows instances of the DSL to be opened and edited in
Visual Studio.

Running the DSL


You can run the DSL solution as soon as you have created it. Later, you can modify the DSL definition gradually,
running the solution again after each change.
To experiment with the DSL
1. Click Transform All Templates in the Solution Explorer toolbar. This regenerates most of the source code
from DslDefinition.dsl.

NOTE
Whenever you change DslDefinition.dsl, you must click Transform All Templates before you rebuild the solution.
You can automate this step. For more information, see How to Automate Transform All Templates.
2. Press F5, or on the Debug menu, click Start Debugging.
The DSL builds and is installed in the experimental instance of Visual Studio.
An experimental instance of Visual Studio starts. The experimental instance takes its settings from a
separate subtree of the registry, where Visual Studio extensions are registered for debugging purposes.
Normal instances of Visual Studio do not have access to extensions registered there.
3. In the experimental instance of Visual Studio, open the model file named Test from Solution Explorer.
- or -
Right-click the Debugging project, point to Add, and then click Item. In the Add Item dialog box, select the
file type of your DSL.
The model file opens as a blank diagram.
The toolbox opens and displays tools appropriate to the diagram type.
4. Use the tools to create shapes and connectors on the diagram.
a. To create shapes, drag from the Example Shape tool onto the diagram.
b. To connect two shapes, click the Example Connector tool, click the first shape, and then click the
second shape.
5. Click the labels of the shapes to change them.
Your experimental Visual Studio will resemble the following example:

The Content of a Model


The content of a file that is an instance of a DSL is called a model. The model contains modelelements and links
between the elements. The DSL definition specifies what types of model elements and links can exist in the model.
For example, in a DSL created from the Minimal Language template, there is one type of model element, and one
type of link.
The DSL definition can specify how the model appears on a diagram. You can choose from a variety of styles of
shapes and connectors. You can specify that some shapes appear inside other shapes.
You can view a model as a tree in the Explorer view while you are editing a model. As you add shapes to the
diagram, the model elements also appear in the explorer. The explorer can be used even if there is no diagram.
If you cannot see the Explorer in the debugging instance of Visual Studio, on the View menu point to Other
Windows, and then click <Your Language> Explorer.
The API of your DSL
Your DSL generates an API that allows you to read and update models that are instances of the DSL. One
application of the API is to generate text files from a model. For more information, see Design-Time Code
Generation by using T4 Text Templates.
In the Debugging solution, open the template files with extension ".tt". These samples demonstrate how you can
generate text from models, and allow you to test the API of your DSL. One of the samples is written in Visual Basic,
the other in Visual C#.
Under each template file is the file that it generates. Expand the template file in Solution Explorer, and open the
generated file.
The template file contains a short segment of code that lists all the elements in the model.
The generated file contains the result.
When you change a model file, you will see corresponding changes in generated files after you regenerate the files.
To r e g e n e r a t e t e x t fi l e s a ft e r y o u c h a n g e t h e m o d e l fi l e

1. In the experimental instance of Visual Studio, save the model file.


2. Make sure that the file name parameter in each .tt file refers to the model file that you are using for
experiments. Save the .tt file.
3. Click Transform All Templates in the toolbar of Solution Explorer.
- or -
Right-click the templates that you want to regenerate and then click Run Custom Tool.
You can add any number of text template files to a project. Each template generates one result file.

NOTE
When you change the DSL definition, the sample text template code will not work, unless you update it.

For more information, see Generating Code from a Domain-Specific Language and Writing Code to Customise a
Domain-Specific Language.

Customizing the DSL


When you want to modify the DSL definition, close the experimental instance and update the definition in the main
Visual Studio instance.

NOTE
After you have modified the DSL definition, you might lose information in the test models that you have created by using
earlier versions. For example, the debugging solution contains a file that is named Sample, which contains some shapes and
connectors. After you start to develop your DSL definition, they will not be visible, and they will be lost when you save the
file.

You can make a wide variety of extensions to your DSL. The following examples will give you an impression of the
possibilities.
After each change, save the DSL definition, click Transform All Templates in Solution Explorer, and then press
F5 to experiment with the changed DSL.
Rename the Types and Tools
Rename the existing domain classes and relationships. For example, starting from a Dsl Definition created from the
Minimal Language template, you could perform the following renaming operations, to make the DSL represent
family trees.
To r e n a m e d o m a i n c l a sse s, r e l a t i o n sh i p s a n d t o o l s

1. In the DslDefinition diagram, rename ExampleModel to FamilyTreeModel, ExampleElement to Person,


Targets to Parents, and Sources to Children. You can click each label to change it.

2. Rename the element and connector tools.


a. Open the DSL Explorer window by clicking the tab under Solution Explorer. If you cannot see it, on
the View menu point to Other Windows and then click DSL Explorer. DSL Explorer is visible only
when the DSL Definition diagram is the active window.
b. Open the Properties window and position it so that you can see DSL Explorer and Properties at the
same time.
c. In DSL Explorer, expand Editor, Toolbox Tabs, <your DSL>, and then Tools.
d. Click ExampleElement. This is the toolbox item that is used to create elements.
e. In the Properties window, change the Name property to Person.
Notice that the Caption property also changes.
f. In the same manner, change the name of the ExampleConnector tool to ParentLink. Alter the
Caption property so that it is not a copy of the Name property. For example, enter Parent Link.
3. Rebuild the DSL.
a. Save the DSL Definition file.
b. Click Transform All Templates in the toolbar of Solution Explorer
c. Press F5. Wait until the experimental instance of Visual Studio appears.
4. In the Debugging solution in the experimental instance of Visual Studio, open a test model file. Drag
elements onto it from the toolbox. Notice that the tool captions and the type names in DSL Explorer have
changed.
5. Save the model file.
6. Open a .tt file and replace occurrences of the old type and property names with the new names.
7. Make sure that the file name that is specified in the .tt file specifies your test model.
8. Save the .tt file. Open the generated file to see the result of running the code in the .tt file. Verify that it is
correct.
Add Domain Properties to Classes
Add properties to a domain class, for example to represent the years of birth and death of a Person.
To make the new properties visible on the diagram, you must add decorators to the shape that displays the model
element. You must also map the properties to the decorators.
To a d d p r o p e r t i e s a n d d i sp l a y t h e m
1. Add the properties.
a. In the DSL Definition diagram, right-click the Person domain class, point to Add, and then click
Domain Property.
b. Type a list of new property names, such as Birth and Death. Press Enter after each one.
2. Add decorators that will display the properties in the shape.
a. Follow the gray line that extends from the Person domain class to the other side of the diagram. This
is a diagram element map. It links the domain class to a shape class.
b. Right-click this shape class, point to Add, and then click Text Decorator.
c. Add two decorators with names such as BirthDecorator and DeathDecorator.
d. Select each new decorator, and in the Properties window, set the Position field. This determines
where the domain property value will be displayed on the shape. For example, set InnerBottomLeft
and InnerBottomRight.

3. Map the decorators to the properties.


a. Open the DSL Details window. It is usually in a tab next to the Output window. If you cannot see it, on
the View menu, point to Other Windows, and then click DSL Details.
b. On the DSL definition diagram, click the line that connects the Person domain class to the shape
class.
c. In DSL Details, on the Decorator Maps tab, click the check box on an unmapped decorator. In
Display Property, select the domain property to which you want it mapped. For example, map
BirthDecorator to Birth.
4. Save the DSL, click Transform All Templates, and press F5.
5. In a sample model diagram, verify that you can now click the positions you chose and type values into them.
In addition, when you select a Person shape, the Properties window displays the new properties Birth and
Death.
6. In a .tt file, you can add code that obtains the properties of each person.
Define New Classes
You can add domain classes and relationships to a model. For example, you could create a new class to represent
towns, and a new relationship to represent that a person lived in a town.
To make the different types distinct on a model diagram, you can map the domain classes to different kinds of
shape, or to shapes with different geometry and colors.
To a d d a n d d i sp l a y a n e w d o m a i n c l a ss

1. Add a domain class and make it a child of the model root.


a. In the DSL Definition diagram, click the Embedding Relationship tool, click the root class
FamilyTreeModel, and then click in an empty part of the diagram.
A new domain class appears, that is connected to the FamilyTreeModel with an embedding
relationship.
Set its name, for example Town.

NOTE
Every domain class except the root of the model must be the target of at least one embedding relationship,
or it must inherit from a class that is the target of an embedding. For this reason, it is frequently convenient
to create a domain class by using the Embedding Relationship tool.

b. Add a domain property to the new class, for example Name.


2. Add a reference relationship between Person and Town.
a. Click the Reference Relationship tool, click Person and then click Town.

NOTE
Reference relationships represent cross-references from one part of the model tree to another.
3. Add a shape to represent towns on the model diagrams.
a. Drag a Geometry Shape from the toolbox to the diagram and rename it, for example TownShape.
b. In the Properties window, set the Appearance fields of the new shape, such as Fill Color and
Geometry.
c. Add a Decorator to display the name of the town, and rename it NameDecorator. Set its Position
property.
4. Map the Town domain class to the TownShape.
a. Click the Diagram Element Map tool, then click the Town domain class, and then the TownShape
shape class.
b. In the Decorator Maps tab of the DSL Details window with the map connector selected, check
NameDecorator and set Display Property to Name.
5. Create a connector to display the relationship between Person and Towns.
a. Drag a Connector from the toolbox to the diagram. Rename it and set its appearance properties.
b. Use the Diagram Element Map tool to link the new connector to the relationship between Person
and Town.

6. Create an element tool for making a new Town.


a. In DSL Explorer, expand Editor then Toolbox Tabs.
b. Right-click <your DSL> and then click Add New Element Tool.
c. Set the Name property of the new tool, and set its Class property to Town.
d. Set the Toolbox Icon property. Click [...] and in the File name field, select an icon file.
7. Create a connector tool for making a link between towns and people.
a. Right-click <your DSL> and then click Add New Connector Tool.
b. Set the Name property of the new tool.
c. In the ConnectionBuilder property, select the builder that contains the name of the Person-Town
relationship.
d. Set the Toolbox Icon.
8. Save the DSL Definition, click Transform All Templates, and then press F5.
9. In the experimental instance of Visual Studio, open a test model file. Use the new tools to create towns and
links between towns and persons. Notice that you can only create links between the correct types of
element.
10. Create code that lists the town in which each person lives. Text templates are one of the places where you
can run such code. For example, you could modify the existing Sample.tt file in the Debugging solution so
that it contains the following code:

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation"


debug="true" #>
<#@ output extension=".txt" #>
<#@ FamilyTree processor="FamilyTreeDirectiveProcessor" requires="fileName='Sample.ftree'" #>

<#
foreach (Person person in this.FamilyTreeModel.People)
{
#>
<#= person.Name #><#if (person.Town != null) {#> of <#= person.Town.Name #> <#}#>

<#
foreach (Person child in person.Children)
{
#>
<#= child.Name #>
<#
}
}
#>

When you save the *.tt file, it will create a subsidiary file that contains the list of people and their residences.
For more information, see Generating Code from a Domain-Specific Language.

Validation and Commands


You could develop this DSL further by adding validation constraints. These constraints are methods that you can
define, that make sure that the model is in a correct state. For example, you could define a constraint to make sure
that the birth date of a child is later than that of its parents. The validation feature displays a warning if the DSL
user tries to save a model that breaks any of the constraints. For more information, see Validation in a Domain-
Specific Language.
You can also define menu commands that the user can invoke. Commands can modify the model. They can also
interact with other models in Visual Studio and with external resources. For more information, see How to: Modify
a Standard Menu Command.

Deploying the DSL


To allow other users to use the domain-specific language, you distribute a Visual Studio Extension (VSIX) file. This
is created when you build the DSL solution.
Locate the .vsix file in the bin folder of your solution. Copy it to the computer on which you want to install it. On
that computer, double-click the VSIX file. The DSL can be used in all instances of Visual Studio on that computer.
You can use the same procedure to install the DSL on your own computer so that you do not have to use the
experimental instance of Visual Studio.
For more information, see Deploying Domain-Specific Language Solutions.

Removing old Experimental DSLs


If you have created experimental DSLs that you no longer want, you can remove them from your computer by
resetting the Visual Studio Experimental instance.
This will remove from your computer all experimental DSLs and other experimental Visual Studio extensions.
These are extensions that have been executed in debugging mode.
This procedure does not remove DSLs or other Visual Studio extensions that have been fully installed by executing
the VSIX file.
To reset the Visual Studio Experimental instance
1. Click Start, click All Programs, Microsoft Visual Studio 2010 SDK, Tools, and then Reset the Microsoft
Visual Studio 2010 Experimental instance.
2. Rebuild any experimental DSLs or other experimental Visual Studio extensions that you still want to use.

See Also
Understanding Models, Classes and Relationships
How to Define a Domain-Specific Language

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.
Understanding Models, Classes and Relationships
10/18/2017 9 min to read Edit Online

A domain-specific language (DSL) is defined by its DSL Definition file, together with any custom program code
that you might write. Most of the program code in the DSL solution is generated from this file.
This topic explains the central features of the DSL definition.

The DSL Definition


When you open Dsl\DslDefinition.dsl , your Visual Studio window resembles the following picture.

The most important information in the DSL Definition is displayed in the DSL Definition diagram. Additional
information, which is also part of DslDefinition.dsl, is displayed in DSL Explorer, which usually appears at the side
of the diagram. You work with the diagram for the most frequent tasks, and with DSL Explorer for more advanced
customizations.
The DSL Definition diagram shows the domain classes that define model elements, and the relationships that
define links between model elements. It also shows the shapes and connectors that are used to display the model
elements to the user.

When you select an item in the DSL definition, either on the diagram or in DSL Explorer, information about it is
displayed in the Properties window. Additional information may be displayed in the DSL Details window.
Models are instances of DSLs
A model is an instance of your DSL created by a user. A model contains model elements, which are instances of
the domain classes that you define, and links between the elements, which are instances of the domain
relationships that you define. A model can also have shapes and connectors, which display the model elements
and links on a diagram. The DSL definition includes the shape classes, connector classes, and a class for the
diagram.
A DSL Definition is also known as a domain model. A DSL Definition or domain model is the design-time
representation of the domain-specific language, whereas the model is the run-time instantiation of the domain-
specific language.

Domain Classes define Model Elements


Domain classes are used to create the various elements in the domain, and domain relationships are the links
between the elements. They are the design-time representation of the elements and links that will be instantiated
by the users of the design-specific language when they create their models.
This illustration shows a model that has been created by the user of a music library DSL. Music albums are
represented by boxes that contain lists of songs. Artists are represented by round-cornered boxes, and are
connected to the albums to which they have contributed.

The DSL Definition separates two aspects. The appearance of the model elements on the model diagram is defined
by using shape classes and connector classes. The information carried in the model is defined using domain
classes and domain relationships.
The following illustration shows the domain classes and relationships in the DSL Definition of the Music Library.

The illustration shows four domain classes: Music, Album, Artist and Song. The domain classes define domain
properties such as Name, Title, and so on. In the instance model, the values of some of these properties are
displayed on the diagram.
Between the classes are domain relationships: MusicHasAlbums, MusicHasArtists, AlbumbHasSongs, and
ArtistAppearedOnAlbums. The relationships have multiplicities such as 1..1, 0..*. For example, every Song must be
related to exactly one Album through the AlbumHasSongs relationship. Every Album can have any number of
Songs.
Rearranging the DSL Definition Diagram
Notice that a domain class can appear several times on the DSL Definition diagram, as Album does in this picture.
There is always one main view, and there can be some reference views.
To rearrange the DSL Definition diagram, you can:
Swap main and reference views by using the Bring Tree Here and Split Tree commands. Right-click a
single domain class to see these commands.
Re-order the domain classes and shape classes by pressing Ctrl+Up and Ctrl+Down.
Collapse or expand classes using the icon at the upper-right of each shape.
Collapse parts of the tree by clicking the minus sign (-) at the bottom of a domain class.

Inheritance
Domain classes can be defined using inheritance. To create an inheritance derivation, click the Inheritance tool,
click the derived class, and then click the base class. A model element has all the properties that are defined on its
own domain class, together with all the properties inherited from the base class. It also inherits its roles in
relationships.
Inheritance can also be used between Relationships, Shapes, and Connectors. Inheritance must keep within the
same group. A shape cannot inherit from a domain class.

Domain Relationships
Model elements can be linked by relationships. Links are always binary; they link exactly two elements. However,
any element can have many links to other objects, and there can even be more than one link between the same
pair of elements.
Just as you can define different classes of elements, you can define different classes of links. The class of a link is
called a domain relationship. A domain relationship specifies what classes of element its instances can connect.
Each end of a relationship is called a role, and the domain relationship defines names for the two roles, as well as
for the relationship itself.
There are two kinds of domain relationships: embedding relationships and reference relationships. On the DSL
Definition diagram, embedding relationships have solid lines at each role, and reference relationships have
dashed lines.
Embedding Relationships
Every element in a model, except for its root, is the target of one embedding link. Therefore, the whole model
forms a single tree of embedding links. An embedding relationship represents containment or ownership. Two
model elements that are related in this way are also known as parent and child. The child is said to be embedded
in the parent.
Embedding links are not usually shown explicitly as connectors on a diagram. Instead, they are usually
represented by containment. The root of the model is represented by the diagram, and elements embedded in it
are displayed as shapes on the diagram.
In the example, the root class Music has an embedding relationship MusicHasAlbums to Album, which has an
embedding AlbumHasSongs to Song. Songs are displayed as items in a list inside each Album. Music also has an
embedding MusicHasArtists to the Artist class, whose instances also appear as shapes on the diagram.
By default, embedded elements are automatically deleted when their parents are deleted.
When a model is saved to file in XML form, embedded elements are nested inside their parents, unless you have
customized the serialization.

NOTE
Embedding is not the same as inheritance. Children in an embedding relationship do not inherit the parent's properties. An
embedding is a type of link between model elements. Inheritance is a relationship between classes, and does not create links
between model elements.

Embedding rules
Every element in an instance model must be the target of exactly one embedding link, except for the root of the
model.
Therefore, every non-abstract domain class, except the root class, must be the target of at least one embedding
relationship, or it must inherit an embedding from a base class. A class can be the target of two or more
embeddings, but its instance model elements can only have one parent at a time. The multiplicity from target to
source must be 0..1 or 1..1.
The Explorer Displays the Embedding Tree
Your DSL Definition also creates an explorer, which users see alongside their model diagram.

The explorer shows all the elements in the model, even those for which you have not defined any shapes. It shows
elements and embedding relationships, but not reference relationships.
To see the values of the domain properties of an element, the user selects an element, either in the model diagram
or in the model explorer, and opens the Properties window. It displays all the domain properties, including those
that are not displayed on the diagram. In the example, each Song has both a Title and a Genre, but only the value
of the Title is shown on the diagram.

Reference Relationships
A reference relationship represents any kind of relationship that is not embedding.
Reference relationships are typically displayed on a diagram as connectors between shapes.
In the XML representation of the model, a reference link between two elements is represented using monikers.
That is, monikers are names that uniquely identify each element in the model. The XML node for each model
element contains a node that specifies the name of the relationship and the moniker of the other element.

Roles
Every domain relationship has two roles, a source role and a target role.
In the following picture, the line between the Publisher domain class and the PublisherCatalog domain
relationship is the source role. The line between the domain relationship and the Album domain class is the target
role.

The names associated with a relationship are especially important when you write program code that traverses
the model. For example, when you build the DSL solution, the generated class Publisher has a property Catalog
that is a collection of Albums. The class Album has a property Publisher that is a single instance of the class
Publisher.
When you create a relationship in a DSL Definition, the property and relationship names are given default values.
However, you can change them.

Multiplicities
Multiplicities specify how many elements can have the same role in a domain relationship. In the example, the
zero-to-many (0..*) multiplicity setting on the Catalog role specifies that any instance of the Publisher domain
class can have as many PublisherCatalog relationship links as you want to give it.
Configure the multiplicity of a role either by typing on the diagram or by modifying the Multiplicity property in
the Properties window. The following table describes the settings for this property.

MULTIPLICITY TYPE DESCRIPTION

0..* (Zero to many) Each instance of the domain class can have multiple instances
of the relationship or no instances of the relationship.

0..1 (Zero to one) Each instance of the domain class can have no more than one
instance of the relationship or no instances of the
relationship.

1..1 (One) Each instance of the domain class can have one instance of
the relationship. You cannot create more than one instance of
this relationship from any instance of the role class. If
validation is enabled, a validation error will appear when any
instance of the role class has no instance of the relationship.

1..* (One to many) Each instance of the class on the role that has this multiplicity
can have multiple instances of the relationship, and each
instance must have at least one instance of the relationship. If
validation is enabled, a validation error will appear when any
instance of the role class has no instance of the relationship.

Domain Relationships as Classes


A link is represented in the Store as an instance of LinkElement, which is a derived class of ModelElement. You can
define these properties in the domain model diagram on domain relationships.
You can also make a relationship the source or target of other relationships. In the domain model diagram, right-
click the domain relationship and then click Show As Class. An additional class box will appear. You can then
connect relationships to it.
You can define a relationship partly by inheritance, just as you can with domain classes. Select the derived
relationship and set Base Relationship in the Properties window.
A derived relationship specializes its base relationship. The domain classes that it links should be derived from or
the same as the classes linked by the base relationship. When a link of the derived relationship is created in a
model, it is an instance of both the derived and the base relationships. In program code, you can navigate to the
opposite end of the link using the properties generated either by the base or by the derived class.

See Also
Domain-Specific Language Tools Glossary
How to Define a Domain-Specific Language
10/18/2017 32 min to read Edit Online

To define a domain-specific language (DSL), you create a Visual Studio solution from a template. The key part of
the solution is the DSL Definition diagram, which is stored in DslDefinition.dsl. The DSL Definition defines the
classes and shapes of the DSL. After you modify and adding to these elements, you can add program code to
customize the DSL in more detail.
If you are new to DSLs, we recommend that you work through the DSL Tools Lab, which you can find in this
site: Visualizaton and Modeling SDK

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK
are installed automatically when you install specific features of Visual Studio. For more details, see this blog
post.

Selecting a Template Solution


To define a DSL, you must have installed the following components:

Visual Studio http://go.microsoft.com/fwlink/?LinkId=185579

Visual Studio SDK http://go.microsoft.com/fwlink/?LinkId=185580

Visual Studio Visualization and Modeling SDK

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK
are installed automatically when you install specific features of Visual Studio. For more details, see this blog
post.

To create a new domain-specific language, you create a new Visual Studio solution using the Domain-Specific
Language project template.
To create a DSL solution
1. Create a solution with the Domain-Specific Language template, which can be found under Other
Project Types/Extensibility in the New Project dialog box.
When you click OK, the Domain-Specific Language Wizard opens and displays a list of template DSL
solutions.
2. Click each template to see a description. Choose the solution that most closely resembles what you want
to create.
Each DSL template defines a basic working DSL. You will edit this DSL to fit your own requirements.
Click each sample for more information.
Select Task Flow to create a DSL that has swimlanes. Swimlanes are vertical or horizontal
partitions of the diagram.
Select Component Models to create a DSL that has ports. Ports are small shapes on the edge of
a larger shape.
Select Class Diagrams to define a DSL that has compartment shapes. Compartment shapes
contain lists of items.
Select Minimal Language in other cases, or if you are uncertain.
Select Minimal WinForm Designer or Minimal WPF Designer to create a DSL that is displayed
on a Windows Forms or WPF surface. You will have to write code to define the editor. For more
information, see the following topics:
Creating a Windows Forms-Based Domain-Specific Language
Creating a WPF-Based Domain-Specific Language
3. Enter a file name extension for your DSL in the appropriate wizard page. This is the extension that files
containing instances of your DSL will use.
Choose a file name extension that is not associated with any application in your computer, or in
any computer where you want to install the DSL. For example, docx and htm would be
unacceptable file name extensions.
The wizard will warn you if the extension that you have entered is being used as a DSL. Consider
using a different file name extension. You can also reset the Visual Studio SDK Experimental
instance to clear out old experimental designers. Click Start, click All Programs, Microsoft
Visual Studio 2010 SDK, Tools, and then Reset the Microsoft Visual Studio 2010
Experimental instance.
4. You can either adjust the settings on the other pages, or leave the default values.
5. Click Finish.
The wizard creates a solution that contains two or three projects, and generates code from the DSL
definition.
The user interface now resembles the following picture.

This solution defines a domain specific language. For more information, see Overview of the Domain-
Specific Language Tools User Interface.
Test the Solution
The template solution provides a working DSL, which you can modify or use as it is.
To test the solution, press F5 or CTRL+F5. A new instance of Visual Studio opens in experimental mode.
In the new instance of Visual Studio, in Solution Explorer, open the Sample file. It opens as a diagram, with a
toolbox.
If you run a solution that you have created from the Minimal Language template, your experimental Visual
Studio will resemble the following example:

Experiment with the tools. Create elements and connect them.


Close the experimental instance of Visual Studio.

NOTE
When you have modified the DSL, you will no longer be able to see the shapes on the Sample test file. However, you will
be able to create new elements.

Modifying the template DSL


Rename and keep some or all of the domain classes and shape classes in the template DSL definition. Your new
class names should be valid CLR names, without spaces or punctuation.
It is especially useful to keep these classes:
The root class appears at the upper-left of the DSL Definition diagram, under Classes and
Relationships. Rename it to a name different from the DSL. For example, a DSL named MusicLibrary
might have a root class named Music.
The diagram class appears at the lower right of the DSL Definition diagram, in the Diagram Elements
column. You might have to scroll to the right to see it. It is typically named YourDslDiagram.
If you used the Task Flow template and you want to create diagrams with swimlanes, keep and rename
the Actor domain class and ActorSwimlane shape.
Delete or rename other classes to suit your requirements.

Patterns for Defining a DSL


We recommend that you develop a DSL by adding or adjusting one or two features at a time. Add a feature, run
the DSL and test it, and then add one or two more features. A typical feature of your DSL might be:
A domain class, the embedding relationship that connects the element to the model, the shape required
to display elements of that class on the diagram, and the element tool that lets users create elements.
The domain properties of a domain class and the decorators that display them on a shape.
A reference relationship and the connector that displays it on the diagram and the connector tool that
lets users create links.
A customization that requires program code, such as a validation constraint or a menu command.
The following sections describe how to construct the most useful kinds of DSL features. There are many
other patterns with which a DSL can be constructed, but these are the most frequently used.

NOTE
After adding a feature, do not forget to click Transform All Templates in the toolbar of Solution Explorer before you
build and running your DSL.

The following figure shows classes and relationships part of the DSL that is used as an example in this topic.

The next figure is an example model of this DSL:


NOTE
"Model" refers to an instance of your DSL that users create, and typically is displayed as a diagram. This topic discusses
both the DSL Definition diagram and the model diagrams that appear when your DSL is used.

Defining Domain Classes


Domain Classes represent the concepts of your DSL. The instances are model elements. For example in a
MusicLibrary DSL you might have Domain Classes named Album and Song.
To create a domain class, you can drag from the Named Domain Class tool to the diagram, and then rename
the class.
For more information, see Properties of Domain Classes.
Create an Embedding Relationship for each Domain Class
Every domain class except the root class must be the target of at least one embedding relationship, or it must
inherit from a class that is the target of an embedding relationship.
In a model, every model element is a node in a single tree of embedding relationships. The source and target of
an embedding relationship are frequently referred to as parent and child.
The selection of a parent for a domain class depends on how you want its elements' lifetimes to depend on
other elements. If a node of a tree is deleted, its sub-tree is usually deleted as well. Classes of element that have
an independent existence are therefore embedded directly under the root class.
Typically, if you display an element inside another element, you want to indicate an owner relationship. In that
case, the most appropriate parent class is the class of the container. The exception is when the item that you see
inside a container is actually just a reference link to an independent element. In that case, deleting the container
deletes the reference but not its target.
In the patterns of DSL definition described in this topic, we will assume that elements displayed inside a
container will be deleted when the container is deleted. More complex schemes are possible, and can be
achieved by defining rules.

HOW ELEMENT IS DISPLAYED PARENT (EMBEDDING) CLASS EXAMPLE IN DSL SOLUTION TEMPLATE

Shape on diagram. Root class of DSL. Minimal Language.

Swimlane. Task Flow: Actor class.


HOW ELEMENT IS DISPLAYED PARENT (EMBEDDING) CLASS EXAMPLE IN DSL SOLUTION TEMPLATE

Shape in swimlane. Domain class of elements that are Task Flow: Task class.
displayed as swimlanes.

Item in list in shape, where item is Domain class that is mapped to the Class diagram: Attribute class.
deleted if container is deleted. container shape.
Component diagram: Port class.
Port on edge of shape.

Item in list, not deleted if container is Root class of DSL.


deleted.
The list displays reference links.

Not directly displayed. The class of which it forms part.

In the Music Library example, Albums are displayed as rectangles in which the titles of Songs are listed.
Therefore the parent of Album is the root class Music, and the parent of Song is Album.
To create a domain class and its embedding at the same time, click the Embedding Relationship tool, then
click the parent class, and then click on a blank part of the diagram.
It is not usually necessary to adjust the name of the embedding relationship and its roles, because they will
track the class names automatically.
For more information, see Properties of Domain Relationships and Properties of Domain Roles.

NOTE
Embedding is not the same as inheritance. Children in an embedding relationship do not inherit features from their
parents.

Add Domain Properties to each Domain Class


Domain properties store values. Examples are: Name, Title, Publication Date.
Click Domain Properties in the class, press the ENTER key, and then type the name of a property. The default
type of a domain property is String. If you want to change the type, select the domain property, and set the
Type in the Properties window. If the type that you want is not in the drop-down list, see Adding Property
Types.
Set an Element Name property. Select a domain property that can be used to identify elements in the
language explorer. For example, in the Song domain class that you could select the Title domain property. In the
Properties window, set Is Element Name to true .
Create Derived Domain Classes
If you want a domain class to have variants that inherit its properties and relationships, create classes that
derive from it. For example, Album might have derived classes WMA and MP3.
Create the derived class using the Domain Class tool.
Click the Inheritance tool, click the derived class, and then click the base class.
Consider setting the Inheritance Modifier of the base class to abstract. If you think that you might need
instances of the base class, consider instead creating a separate derived class for them.
Derived classes inherit the properties and roles of their base classes.
Tidy the DSL Definition Diagram
When you add relationships, some of your classes will appear in more than one place. To reduce the number of
appearances and make the diagram wider, right-click the target class of a relationship, and then click Bring
Tree Here. For the opposite effect, right-click the target class of a relationship and click Split Tree. If you do not
see these menu commands, make sure that only the domain class is selected.
Use CTRL+Up and CTRL+Down to move domain classes and shape classes.
Test the domain classes
To t e st t h e n e w D o m a i n C l a sse s

1. Click Transform All Templates in the toolbar of Solution Explorer, to generate the DSL designer code.
You can automate this step. For more information, see How to Automate Transform All Templates.
2. Build and run the DSL. Press F5 or CTRL+F5 to run a new instance of Visual Studio in experimental
mode. In the experimental instance of Visual Studio, open or create a file that has the file name extension
of your DSL.
3. Open the Explorer. At the side of the diagram is the language explorer window, which is usually named
YourLanguage Explorer. If you do not see this window, it might be on a tab underneath Solution
Explorer. If you cannot find it, on the View menu, point to Other Windows, and then click
YourLanguageExplorer.
Your explorer presents a tree view of the model.
4. Create new elements. Right-click the root node at the top, and then click Add NewYourClass.
A new instance of your class appears in your language Explorer.
5. Verify that each instance has a different name when you create new instances. This will occur only if you
have set the Is Element Name flag on a domain property.
6. Examine the domain properties. With an instance of your class selected, inspect the Properties
window. It should show the domain properties that you defined on this domain class.
7. Save the file, close it, and re-open it. All the instances you created should be visible in the explorer,
after you expand the nodes.

Defining Shapes on the Diagram


You can define classes of elements that appear on a diagram as rectangles, ellipses, or icons.
To define a class of elements that appear as shapes on a diagram
1. Define and test a domain class as described in Defining Domain Classes .
The parent of the class should be the root class. That is, there should be an embedding
relationship between the root class and the new domain class.
If your diagram has swimlanes, the parent can be the domain class that is mapped to a swimlane.
Before continuing with this procedure, see Defining a DSL that has Swimlanes.
2. Add a shape class to represent the elements on the model diagram. Drag from one of the following
tools onto the DSL Definition diagram:
Geometry Shape provides a rectangle or ellipse.
Image Shape displays an image that you provide.
Compartment Shape is a rectangle that contains one or more lists of items.
Rename the shape class, which will appear on the right side of the DSL Definition diagram, under
Shapes and Connectors.
3. Define an image, if you created an image shape.
a. Create an image file of any size. BMP, JPEG, GIF and EMF formats are supported.
b. In Solution Explorer, add the file to the solution under Dsl\Resources.
c. Return to the DSL Definition diagram and select the new image shape class.
d. In the Properties window, click the Image property.
e. In the Select Image dialog box, click the drop-down menu under File name, and select the
image.
4. Add text decorators to the shape, to display the domain properties.
To display the name or title of the model element, you will probably need at least one text decorator.
Right-click the header of the shape class, point to Add, and then click Text Decorator. Set the name of
the decorator, and in the Properties window set its Position.
5. Connect each shape with a Diagram Element Map to the domain class that it should display.
Click the Diagram Element Map tool, then click the domain class, then click the shape class.
6. Map the properties to the text decorators.
a. Select the gray line between the domain class and the shape class that represents the diagram
element map.
b. In the DSL Details window, click the Decorator Maps tab. If you do not see the DSL Details
window, on the View menu, point to Other Windows and then click DSL Details. It is frequently
necessary to raise the top of this window to see all its content.
c. Select the name of a decorator. Under Display property, select the name of a property of the
domain class. Repeat this for each decorator.
If you want to display a property of a related element, click the drop-down tree navigator under
Path to display property.
d. Make sure that a check mark appears alongside each decorator name.
7. Make a toolbox item for creating elements of the domain class.
a. In DSL Explorer, expand the Editor node and all its sub-nodes.
b. Right-click the node under Toolbox Tabs that has the same name as your DSL, for example
MusicLibrary. Click Add Element Tool.

NOTE
If you right-click the Tools node, you will not see Add Element Tool. Instead, click the node above it.

c. In the Properties window with the new element tool selected, set Class to the domain class that
you have recently added.
d. Set Caption and Tooltip.
e. Set Toolbox Icon to an icon that will appear in the toolbox. You can set it to a new icon or an icon
already used for another tool.
To create a new icon, open Dsl\Resources in Solution Explorer. Copy and paste one of the
existing element tool BMP files. Rename the pasted copy, and then double-click to edit it.
Return to the DSL Definition diagram, select the tool, and in the Properties window click [...] in
Toolbox Icon. In the Select Bitmap dialog box, select your .BMP file from the drop-down menu.
For more information, see Properties of Geometry Shapes and Properties of Image Shapes.
To Test Shapes
1. Click Transform All Templates in the toolbar of Solution Explorer, to generate the DSL designer code.
2. Build and run the DSL. Press F5 or CTRL+F5 to run a new instance of Visual Studio in experimental
mode. In the experimental instance of Visual Studio, open or create a file that has the file name extension
of your DSL.
3. Verify that the element tools appear on the toolbox.
4. Create shapes by dragging from a tool onto the model diagram.
5. Verify that each text decorator appears, and that:
a. You can edit it, unless you have set the Is UI Read Only flag on the domain property.
b. When you edit the property either in the Properties window or in the decorator, the other view is
updated.
After you first test a shape, you might want to adjust some its properties and add some more advanced
features. For more information, see Customizing and Extending a Domain-Specific Language.

Defining Reference Relationships


You can define a reference relationship between any source domain class and any target domain class.
Reference relationships are typically displayed on a diagram as connectors, which are lines between shapes.
For example, if music Albums and Artists are displayed as shapes on your diagram, you could define a
relationship named ArtistsAppearedOnAlbums that links Artists to the Albums on which they have worked. See
the example in the figure.

Reference relationships can also link elements of the same type. For example, in a DSL representing a family
tree, the relationship between parents and their children is a reference relationship from Person to Person.
Define a Reference Relationship
Click the Reference Relationship tool, then click the source domain class of the relationship, and then click the
target domain class. The target class can be the same as the source class.
Each relationship has two roles, represented by the line at each side of the relationship box. You can select each
role and set its properties in the Properties window.
Consider renaming the roles. For example, in a relationship between Person and Person, you might want to
change the default names to Parents and Children, Manager and Subordinates, Teacher and Student, and so on.
Adjust the multiplicities of each role, if it is necessary. If you want each Person to have at most one
Manager, set the multiplicity that appears below the Manager label on the diagram to 0..1.
Add domain properties to the relationship. In the figure, the Artist-Album relationship has a property of
role.
Set the Allows Duplicates property of the relationship, if more than one link of the same class can exist
between the same pair of model elements. For example, you could allow a Teacher to teach more than one
Subject to the same Student.
For more information, see Properties of Domain Relationships and Properties of Domain Roles.
Define a Connector to Display the Relationship
A connector displays a line between two shapes on the model diagram.
Drag the Connector tool onto the DSL definition diagram.
Add text decorators if you want to display labels on the connector. Set their positions. To let the user move a
text decorator, set its Is Moveable property.
Use the Diagram Element Map tool to link the connector to the reference relationship.
With the diagram element map selected, open the DSL Details window, and open the Decorator Maps tab.
Select each Decorator and set Display property to the correct domain property.
Make sure that a check mark appears next to each item in the Decorators list.
Define a Connection Builder Tool
In the DSL Explorer window, expand the Editor node and all its subnodes.
Right-click the node that has the same name as your DSL, and then click Add New Connection Tool.
While the new tool is selected, in the Properties window:
Set the Caption and Tooltip.
Click Connection Builder and select the appropriate builder for the new relationship.
Set Toolbox Icon to the icon that you want to appear in the toolbox. You can set it to a new icon or an
icon already used for another tool.
To create a new icon, open Dsl\Resources in Solution Explorer. Copy and paste one of the existing
element tool BMP files. Rename the pasted copy, and then double-click to edit it.
Return to the DSL Definition diagram, select the tool, and in the Properties window click [...] in Toolbox
Icon. In the Select Bitmap dialog box, select your .BMP file from the drop-down menu.
To Te st a R e fe r e n c e R e l a t i o n sh i p a n d C o n n e c t o r

1. Click Transform All Templates in the toolbar of Solution Explorer, to generate the DSL designer code.
2. Build and run the DSL. Press F5 or CTRL+F5 to run a new instance of Visual Studio in experimental
mode. In the experimental instance of Visual Studio, open or create a file that has the file name extension
of your DSL.
3. Verify that the connection tool appears on the toolbox.
4. Create shapes by dragging from a tool onto the model diagram.
5. Create connections between the shapes. Click the connector tool, click a shape, and then click another
shape.
6. Verify that you cannot create connections between inappropriate classes. For example, if your
relationship is between Albums and Artists, verify that you cannot link Artists to Artists.
7. Verify that the multiplicities are correct. For example, verify that you cannot connect a Person
to more than one manager.
8. Verify that each text decorator appears, and that:
a. You can edit it, unless you have set the Is UI Read Only flag on the domain property.
b. When you edit the property either in the Properties window or in the decorator, the other view is
updated.
After you first test a connector, you might want to adjust some its properties and add some more
advanced features. For more information, see Customizing and Extending a Domain-Specific Language.

Defining Shapes that Contain Lists: Compartment Shapes


A compartment shape contains one or more lists of items. For example, in a Music Library DSL, you could use
compartment shapes to represent music Albums. In each Album, there is a list of Songs.

In the simplest method of achieving this effect in a DSL definition, you define one domain class for the
container, and one domain class for each list. The container class is mapped to the compartment shape.

For more information, see Properties of Compartment Shapes.


To define a Compartment Shape
1. Create the container domain class. Click the Embedding Relationship tool, click the root class of the
model, and then click a blank part of the DSL definition diagram. This creates the domain class that is
named Album in the example figure.
Alternatively instead of embedding in the root class, you can embed the container in a domain class that
is mapped to a swimlane.
Add a domain property such as Name to the class, and set its Is Element Name flag in the Properties
window.
2. Create the list item domain class. Click the Embedding Relationship tool, click the container class
(Album) and then click a blank part of the diagram. This creates the domain class that is named Song in
the example figure.
Add a domain property such as Title to the class, and set its Is Element Name flag.
Add other domain properties.
Add another list item domain class for each list that you want to display.
3. To mix several types of item in the list, create classes that inherit from the list class. Make the list
class abstract by setting its Inheritance Modifier.
For example, if you want classical music to be sorted by composer instead of artist, you could create two
subclasses of Song, ClassicalSong and NonClassicalSong.
4. Create the compartment shape. Drag from the Compartment Shape tool onto the DSL definition
diagram.
Add a text decorator and set its name.
Add a compartment and set its name.
5. To let the user hide the list compartments, right-click the compartment shape class, point to Add, and
then click Expand/Collapse Decorator. In the Properties window, set the position of the decorator.
6. Click the Diagram Element Map tool, click the container domain class, and then click the compartment
shape.
7. Select the diagram element map link between the domain class and the shape. In the DSL Details
window:
a. Click the Decorators tab. Click the name of the decorator and then select the appropriate item
under Display Property. Make sure that a check mark appears next to the name of the decorator.
b. Click the Compartment Maps tab.
Click the name of the compartment.
Under Displayed elements collection path, navigate to the list element class (Song). Click the
drop-down arrow to use the navigator tool.
Under Display Property, select the property that should be displayed in the list. In the example,
this is Title.

NOTE
By using the Path fields in the Decorator Map and Compartment map fields, you can make more complex relationships
between the domain classes and the compartment shape.

To define a tool for creating the shape


1. Make a toolbox item for creating elements of the domain class.
2. In DSL Explorer, expand the Editor node and all its sub-nodes.
3. Right-click the node under Toolbox Tabs that has the same name as your DSL, for example
MusicLibrary. Click Add Element Tool.
NOTE
If you right-click the Tools node, you will not see Add Element Tool. Instead, click the node above it.

4. In the Properties window with the new element tool selected, set Class to the domain class that you have
recently added.
5. Set Caption and Tooltip.
6. Set Toolbox Icon to an icon that will appear in the toolbox. You can set it to a new icon or an icon
already used for another tool.
To create a new icon, open Dsl\Resources in Solution Explorer. Copy and paste one of the existing
element tool .BMP files. Rename the pasted copy, and then double-click to edit it.
Return to the DSL Definition diagram, select the tool, and in the Properties window click [...] in Toolbox
Icon. In the Select Bitmap dialog box, select your BMP file from the drop-down menu.
To test a compartment shape
1. Click Transform All Templates in the toolbar of Solution Explorer, to generate the DSL designer code.
2. Build and run the DSL. Press F5 or CTRL+F5 to run a new instance of Visual Studio in experimental
mode. In the experimental instance of Visual Studio, open or create a file that has the file name extension
of your DSL.
3. Verify that the tool appears on the toolbox.
4. Drag the tool onto the model diagram. A shape is created.
Verify that the name of the element appears and is set automatically to a default value.
5. Right-click the header of the new shape, and then click Add Your List Item. In the example, the command
is Add Song.
Verify that an item appears in the list and that it has a new name.
6. Click one of the list items, and then examine the Properties window. You should see the properties of the
list items.
7. Open the language Explorer. Verify that you can see the container nodes with the list item nodes inside.

After you first test a compartment shape, you might want to adjust some of its properties and add some
more advanced features. For more information, see Customizing and Extending a Domain-Specific
Language.
Displaying a Reference Link in a Compartment
Usually, an element that you display in a compartment is a child of the element that is represented by the
compartment shape. But sometimes, you would like to display an element that is linked to it with a reference
relationship.
For example, we could add a second compartment to AlbumShape that displays a list of the Artists that are
linked to the Album.
In this case, the compartment should display the link, instead of the referenced element. This is because when
the user selects the item in the compartment and presses DELETE, you want the link to be deleted, not the
referenced element.
Nevertheless, you can have the name of the referenced element appear in the compartment.
The following procedure assumes that you have already created the domain class, the reference relationship,
the compartment shape, and the diagram element map, as described earlier in this section.
To d i sp l a y a r e fe r e n c e l i n k i n a c o m p a r t m e n t

1. Add a compartment to the compartment shape. On the DSL Definition diagram, right-click the
compartment shape class, point to Add, and then click Compartment.
2. Set Displayed elements collection path to navigate to the link, instead of its target element. Click the
drop-down menu and use the tree view to select the reference relationship instead of its target. In the
example, the relationship is ArtistAppearedOnAlbums.
3. Set Path to Display Property to navigate from the link to the target element. In the example, this is
Artist.
4. Set Display Property to the appropriate property of the target element, for example Name.
5. Transform All Templates, build and run the DSL, and open a test model.
6. In the model diagram, create the appropriate classes of shape, set their names, and create a link between
them. In the compartment shape, the names of linked elements should appear.
7. Select either the link or the item in the compartment shape. Both the link and the item should disappear.

Defining Ports on the Boundary of another Shape


A port is a shape that is located on the boundary of another shape.
Ports can also be used to provide a fixed connection point on another shape, to which the user can draw
connectors. In this case, you can make the port shape transparent.
To see an example that uses ports, select the Component Diagram template when you create a new DSL
solution. This example shows the main points that you can consider when you define ports:
There is a domain class that represents the container of the ports, Component .
There is a domain class that represents ports. In the example, this is ComponentPort .
There is an embedding relationship from the container domain class to the port domain class. For more
information, see Defining Domain Classes.
If you want different types of port to be mixed on the same container, you can create subclasses of the
port domain class. In the example, InPort and OutPort inherit from ComponentPort .
The container domain class can be mapped to any kind of shape. In the example, it is ComponentShape .
For more information, see Defining Shapes.
The port domain classes are mapped to port shapes. You can either map the derived classes to separate
port shape classes, or map the base class to one port shape class.
In other respects, port shapes behave as described in Defining Shapes.
For more information, see Properties of Port Shapes.
Defining a DSL that has Swimlanes
Swimlanes are a horizontal or vertical partition of a diagram. Each swimlane corresponds to a model element.
Your DSL definition requires one domain class for the swimlane elements.
The best way to create a DSL with swimlanes is to create a new DSL solution and choose the Task Flow solution
template. In the DSL Definition, the Actor class is the domain class mapped to the swimlane. Rename this and
the other classes to suit your project.
To add a class that will be displayed as a shape inside a swimlane, create an Embedding Relationship between
the swimlane class and your new class. Users will be able to drag elements from one swimlane to another, but
each element will always be inside a particular swimlane. In the Task Flow solution template, FlowElement is a
child of the swimlane class.
To add a class that will be displayed as a shape independently of swimlanes, create an Embedding Relationship
between the root class and your new class. Users will be able to place these shapes anywhere on the diagram,
including across the boundaries of swimlanes and outside the swimlanes. In the Task Flow solution template,
Comment is a child of the root class.
For more information, see Properties of Swimlanes.

Adding Property Types


Domain Enumerations and Literals
A domain enumeration is a type with several literal values.
To add a domain enumeration, right-click the root of the model in the DSL Explorer and then click Add New
Domain Enumeration. The element will appear in the DSL Explorer under the Domain Types node. This
element does not appear on the diagram.
To add enumeration literals to the domain enumeration, right-click the domain enumeration in the DSL
Explorer and then click Add New Enumeration Literal.
By default, a property that has an enumeration type can be set to only one value of the enumeration at a time. If
you want users and programmers to be able to set any combination of values - a "bit field" - set the IsFlags
property of the Enumeration.
External Types
When you set the type of a domain property, if you do not find the type you want in the Type drop-down list,
you can add an external type. For example, you could add the System.Drawing.Color type to the list.
To add a type, right-click the root of the model in DSL Explorer, and then click Add New External Type. In the
Properties window, set the name to Color and the namespace to System.Drawing. This type now appears in
DSL Explorer under Domain Types. You can choose it whenever you set the type of a domain property.

Customizing the DSL


Using the techniques described in this topic, you can quickly create a DSL with a diagrammatic notation, a
readable XML form, and the basic tools that are required to generate code and other artifacts.
There are two methods of extending the DSL definition:
1. Fine-tune the DSL by using more features of the DSL Definition. For example, you can make a single
connector tool that can create several types of connector, and you can control the rules by which deleting
one element also deletes related elements. These techniques are mostly achieved by setting values in the
DSL Definition, and some require a few lines of program code.
For more information, see Customizing and Extending a Domain-Specific Language.
2. Extend your modeling tools by using program code to achieve more advanced effects. For example, you
can create menu commands that can change the model, and you can create tools that integrate two or
more DSLs. VMSDK is designed specifically to make it easy to integrate your extensions with the code
that is generated from the DSL Definition. For more information, see Writing Code to Customise a
Domain-Specific Language.
Changing the DSL Definition
When you create any item in a DSL definition, many default values are set automatically. After they have been
set, you can change them. This simplifies the development of a DSL, while still allowing for powerful
customizations.
For example, when you map a shape to an element, the Parent Element Path of the mapping is automatically set
according to the embedding relationship of the domain class. However, if you later change the embedding
relationship, the parent element path is not changed automatically.
You should therefore be aware that when you change some relationships in your DSL Definition, it is not
unusual for errors to be reported either when you save the definition, or when you Transform All Templates.
Most of these errors are easy to fix. Double-click the error report to see the location of the error.
See also How to: Change the Namespace of a Domain-Specific Language.

Troubleshooting
The following table lists some of the most common problems that are encountered when you design a DSL,
together with suggestions for their solution. More advice is available on the Visualization Tools Extensibililty
Forum.

PROBLEM SUGGESTION

The changes I have made in the DSL Definition file have no Click Transform All Templates in the toolbar above
effect. Solution Explorer, and then rebuild the solution.

Shapes show the name of a decorator instead of the Set up the decorator mapping. On the DSL Definition
property value. diagram, click the diagram element map, which is the gray
line between the domain class and the shape class.

Open the DSL Details window. If you cannot see it, on the
View menu, point to Other Windows, and then click DSL
Details.

Click the Decorator Maps tab. Select the name of the


decorator. Make sure that the box next to it is checked.
Under Display property, select the name of a domain
property.

For more information, see Shapes on the Diagram.

In DSL Explorer, I cannot add to a collection. For example, Right-click the item above the node that you are trying.
when I right-click Tools, there is no "Add Tool" command in When you want to add to a list, the Add command is not in
the menu. the list node, but in its owner.

In the explorer for my DSL, I cannot add an element to a list.

I created a domain class, but I can't create instances in the Every domain class except the root must be the target of an
language explorer. embedding relationship.
PROBLEM SUGGESTION

In the explorer for my DSL, elements are shown only with In the DSL Definition, select a domain property of the class
their type names. and in the Properties window, set Is Element Name to true.

My DSL always opens in the XML editor. This can happen because of an error while the file was being
read. However, even after you fix that error, you must
explicitly reset the editor to be your DSL designer.

Right-click the project item, click Open With and select


YourLanguageDesigner (Default).

The toolbox of my DSL does not appear after I changed the Inspect and update
assembly names. DslPackage\GeneratedCode\Package.tt For more
information, see How to: Change the Namespace of a
Domain-Specific Language.

The toolbox of my DSL does not appear, but I have not Reset the experimental instance, and rebuild your solution.
changed the assembly name.
1. At the Windows Start menu, under All Programs,
Or, a message box appears reporting the failure to load an expand Visual Studio SDK, then Tools, and then click Reset
extension. the Microsoft Visual Studio Experimental Instance.
2. On the Visual StudioBuild menu, click Rebuild Solution.

See Also
Getting Started with Domain-Specific Languages
Creating a Windows Forms-Based Domain-Specific Language
Creating a WPF-Based Domain-Specific Language

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK
are installed automatically when you install specific features of Visual Studio. For more details, see this blog
post.
Customizing and Extending a Domain-Specific
Language
10/31/2017 6 min to read Edit Online

Visual Studio Modeling and Visualization SDK (VMSDK) provides several levels at which you can define
modeling tools:
1. Define a domain-specific language (DSL) using the DSL Definition diagram. You can quickly create a DSL
with a diagrammatic notation, a readable XML form, and the basic tools that are required to generate
code and other artifacts.
For more information, see How to Define a Domain-Specific Language.
2. Fine-tune the DSL by using more advanced features of the DSL Definition. For example, you can make
additional links appear when the user creates an element. These techniques are mostly achieved in the
DSL Definition, and some require a few lines of program code.
3. Extend your modeling tools by using program code. VMSDK is designed specifically to make it easy to
integrate your extensions with the code that is generated from the DSL Definition. For more information,
see Writing Code to Customise a Domain-Specific Language.

NOTE
When you have updated the DSL Definitions file, do not forget to click Transform All Templates in the toolbar of
Solution Explorer before rebuilding your solution.

In this Section
TO ACHIEVE THIS EFFECT REFER TO THIS TOPIC

Allow the user to set the color and style properties of a Right-click the shape or connector class, point to Add
shape. Exposed, and click an item.

See Customizing Presentation on the Diagram.

Different classes of model element look similar on the Use inheritance between shapes or connector classes.
diagram, sharing properties such as initial height and width, Mappings between derived shapes and derived domain
color, tooltips. classes inherit the mapping details of the parents.

Or, map different domain classes to the same shape class.

A class of model element is displayed by different shapes Map more than one shape class to the same domain class.
contexts. When you build the solution, follow the error report and
provide the requested code to decide what shape to use.
TO ACHIEVE THIS EFFECT REFER TO THIS TOPIC

Shape color or other features such as font indicate current See Updating Shapes and Connectors to Reflect the Model.
state.
Create a rule that updates the exposed properties. See Rules
Propagate Changes Within the Model.

Or, use OnAssociatedPropertyChanged() to update non-


exposed features such as link arrows or font.

Icon on shape changes to indicate state. Set the visibility of the decorator mapping in the DSL Details
window. Locate several image decorators on the same
position. See Updating Shapes and Connectors to Reflect the
Model.

Or, override ImageField.GetDisplayImage() . See example


in ImageField.

Set a background image on any shape Override InitializeInstanceResources() to add an anchored


ImageField. See Customizing Presentation on the Diagram.

Nest shapes to any depth Set up a recursive embedding tree. Define BoundsRules to
contain the shapes. See Customizing Presentation on the
Diagram.

Attach connectors at fixed points on an element's boundary. Define embedded terminal elements, represented by small
ports on the diagram. Use BoundsRules to fix the ports in
place. See the Circuit Diagram sample at Visualization and
Modeling SDK.

Text field displays a value derived from other values. Map the text decorator to a Calculated or Custom Storage
domain property. For more information, see Calculated and
Custom Storage Properties.

Propagate changes between model elements, or between See Validation in a Domain-Specific Language.
shapes

Propagate changes to resources such as other Visual Studio See Event Handlers Propagate Changes Outside the Model.
extensions outside the store.

Property window displays properties of a related element. Set up Property Forwarding. See Customizing the Properties
Window.

Property categories The properties window is divided into sections called


categories. Set the Category of your domain properties.
Properties with the same category name will appear in the
same section. You can also set the Category of a
relationship role.

Control user access to domain properties Set Is Browsable false to prevent a domain property from
appearing in the Properties window at run time. You can still
map it to text decorators.

Is UI Read Only prevents users from changing a domain


property.

Program access to the domain property is not affected.


TO ACHIEVE THIS EFFECT REFER TO THIS TOPIC

Change the name, icon, and visibility of nodes in your DSL's See Customizing the Model Explorer.
model explorer.

Enable copy, cut and paste Set the Enable Copy Paste property of the Editor node in
DSL Explorer.

Copy reference links and their targets whenever an element Set the Propagates Copy property of the source role
is copied. For example, copy Comments attached to an item. (represented by the line at one side of the domain
relationship in the DSL Definition diagram).

Write code to override ProcessOnCopy to achieve more


complex effects.

See Customizing Copy Behavior.

Delete, reparent, or relink related elements when an element Set the Propagates Delete value of a relationship role. For
is deleted. more complex effects, override ShouldVisitRelationship
and ShouldVisitRolePlayer methods in the
MyDslDeleteClosure class, defined in DomainModel.cs

See Customizing Deletion Behavior

Preserve shape layout and appearance on copy and drag- Add the shapes and connectors to the copied
drop. ElementGroupPrototype . The most convenient method to
override is
ElementOperations.CreateElementGroupPrototype()

See Customizing Copy Behavior.

Paste shapes in a chosen location, such as the current cursor Override ClipboardCommandSet.ProcessOnCopy() to use
position. the location-specific version of
ElementOperations.Merge(). See Customizing Copy
Behavior.

Create additional links on paste Override


ClipboardCommandSet.ProcessOnPasteCommand()

Enable drag and drop from this diagram, other DSLs and See How to: Add a Drag-and-Drop Handler
Windows elements

Allow a shape or tool to be dragged onto a child shape, Define an Element Merge Directive on the target object
such as a port, as if it were dragged onto the parent. class, to forward the dropped object to the parent. See
Customizing Element Creation and Movement.

Allow a shape or tool to be dragged onto a shape and have Define an Element Merge Directive on the target domain
additional links or objects created. For example, to allow a class, and define the links to be generated. In complex cases,
comment to be dropped onto an item to which it is to be you can add custom code. See Customizing Element
linked. Creation and Movement.
TO ACHIEVE THIS EFFECT REFER TO THIS TOPIC

Create a group of elements with one tool. For example, a Override the toolbox initialization method in
component with a fixed set of ports. ToolboxHelper.cs. Create an Element Group Prototype (EGP)
containing the elements and their relationship links. See
Customizing Tools and the Toolbox.

Either include the principal and port shapes in the EGP, or


define BoundsRules to position the port shapes when the
EGP is instantiated. See BoundsRules Constrain Shape
Location and Size.

Use one connection tool to instantiate several types of Add Link Connect Directives (LCD) to the Connection Builder
relationship. that is invoked by the tool. The LCDs determine the type of
the relationship from the types of the two elements. To
make this depend on the states of the elements, you can
add custom code. See Customizing Tools and the Toolbox.

Sticky tools - the user can double-click any tool to create In DSL Explorer, select the Editor node. In the Properties
many shapes or connectors in succession. window, set Uses Sticky Toolbox Items.

Define menu commands See How to: Modify a Standard Menu Command

Constrain the model with validation rules See Validation in a Domain-Specific Language

Generate code, configuration files, or documents from a Generating Code from a Domain-Specific Language
DSL.

Customize how models are saved to file. See Customizing File Storage and XML Serialization

Save models to databases or other media. Override YourLanguageDocData

See Customizing File Storage and XML Serialization

Integrate several DSLs so that they work as part of one See Integrating Models by using Visual Studio Modelbus.
application.

Allow your DSL to be extended by third parties, and control Extend your DSL by using MEF
the extension.
Sharing Classes between DSLs by using a DSL Library

Defining a Locking Policy to Create Read-Only Segments

See Also
How to Define a Domain-Specific Language
Writing Code to Customise a Domain-Specific Language
Modeling SDK for Visual Studio - Domain-Specific Languages

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK
are installed automatically when you install specific features of Visual Studio. For more details, see this blog
post.
Customizing Presentation on the Diagram
10/18/2017 1 min to read Edit Online

The diagram is the main presentation area of a domain-specific language designer. Usually, users will use the
diagram to construct their models. You can customize the diagram as described in the following topics.
Defining Shapes and Connectors
Controlling Color, Line Style, and other Shape Properties
Controlling the Visibility of an Icon or Decorator
Customizing Text and Image Fields
Setting a Background Image on a Diagram
Nesting Shapes
Embedding a Diagram in a Windows Form

See Also
Navigating and Updating a Model in Program Code
Defining Shapes and Connectors
10/18/2017 2 min to read Edit Online

There are several basic types of shapes that you can used to display information on a diagram in a domain-specific
language (DSL).

Basic Types of Shapes and Connectors


A DSL diagram shows a collection of shapes interlinked by lines or connectors. Typically, but not always:
Shapes are the visible representation of model elements.
Connectors represent reference relationships.
The diagram represents the model root instance.
Embedding relationships between model elements are shown by containment. For example, elements
representing component ports are embedded in the component.
These patterns are not enforced, but are more strongly supported. When you design a DSL, bear in mind
that the design of the embedding relationships should be influenced by how you want to present the model
on the screen. By contrast, the reference relationships should reflect the concepts of your business domain.
The following types of shapes are available:

SHAPE TYPE DESCRIPTION

Geometry shape General purpose rectangular or elliptical shape. You can


display text and icon decorators in specific positions relative to
the bounds of the shape.

To nest shapes inside geometry shapes, see Nesting Shapes.

Compartment shape Rectangle containing a header and compartments, like a UML


class. Each compartment can contain a list of text rows.

The rows typically represent elements embedded under the


element represented by the shape. For an example, create a
DSL from the Class Diagrams solution template.

Image shape Shape that displays an image.


SHAPE TYPE DESCRIPTION

Port shape A small rectangle designed to attach to the outline of another


shape. Typically used in component models.

The model element represented by a port is typically


embedded under the element represented by the parent
shape. For an example, create a DSL by using the Components
solution template.

By default, a port shape can slide along the sides of its parent.
You can define a Bounds Rule to constrain it to a particular
position.

By making a port shape very small and transparent, you can


use it to provide a fixed connection point on the surface of its
parent shape.

Swimlanes Swimlanes partition a diagram into horizontal or vertical


segments. The swimlane always stays underneath the other
shapes on the diagram.

Typically the model elements of the swimlane are parented on


the model root, and the other elements are parented on
them. For an example, create a DSL from the Task Flow
solution template.

Connectors The lines drawn between shapes typically represent reference


relationships. You can set options to make a connector
straight or rectilinear, and to have different types of
arrowhead.

Shape Inheritance
A shape can inherit from another shape. However, the shapes must be the same kind. For example, only a
geometry shape can inherit from a geometry shape. Inherited shapes have the compartments and decorators of
their base shape. Connectors can inherit from connectors.
Controlling Color, Line Style, and other Shape
Properties
10/18/2017 1 min to read Edit Online

Some shape properties such as color can be 'exposed' - that is, linked to a domain property of the shape. Others
have to be controlled directly.

Exposing a property
Some shape properties such as color can be linked to the value of a domain property.
In the DSL Definition, select a shape, connector or diagram class. On its context menu, choose Add Exposed, and
then choose the property you want, such as Fill Color.
The shape now has a domain property that you can set in program code or as a user.

Dynamically updating an exposed property


Typically you want to make the exposed property dependent on another property. For example, you might want a
shape to turn red whenever a particular domain property is less than zero. To make this dependency, create a rule.
For example:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
namespace ExampleNamespace
{
// Attribute associates the rule with class:
[RuleOn(typeof(CarShape), FireTime = TimeToFire.TopLevelCommit)]
// The rule is a class derived from one of the abstract rules:
class CarShapeAddRule : AddRule
{
// Override the abstract method:
public override void ElementAdded(ElementAddedEventArgs e)
{
base.ElementAdded(e);
CarShape shape = e.ModelElement as CarShape;
Store store = shape.Store;
// Ignore this call if we're currently loading a model:
if (store.TransactionManager.CurrentTransaction.IsSerializing)
return;
Car car = shape.ModelElement as Car;
// Code here propagates change as required - for example:
shape.FillColor = car.Somebool ? System.Drawing.Color.Red : System.Drawing.Color.Green;
}
}
// The rule must be registered:
public partial class ExampleDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(CarShapeAddRule));
// If you add more rules, list them here.
return types.ToArray();
}
}
}
Controlling the Visibility of an Icon or Decorator
10/18/2017 3 min to read Edit Online

A decorator is an icon or line of text that appears on a shape in a domain-specific language (DSL). You can make
the decorator appear and disappear depending on the state of properties in the model. For example, on a shape
representing a Person, you could have different icons that appear depending on the person's gender, number of
children, and so on.

Controlling the visibility of an icon or decorator


The following procedure assumes that you have already defined a shape and its mapping to a domain class. For
more information, see How to Define a Domain-Specific Language.
To control the visibility of an icon or text decorator
1. In the DSL Definition diagram, add to the shape class the icons or text decorators that you want to appear.
a. Right-click the shape class, point to Add, and then click the required type of decorator.
b. Set the decorator's Position property. More than one decorator can have the same position. For
example, you could have icons for male and female sharing the same position.
c. Set the Default Icon property of an icon decorator.
2. Select the diagram element map, which is the gray line between the shape class and the domain class on the
DSL Definition diagram.
3. In the DSL Details window, in the Decorator Maps tab, select a decorator. For example, the MaleDecorator.
4. Check the Visibility Filter box.
5. If the domain property that should control visibility is on the immediate domain class, leave Path to Filter
Property blank.
Otherwise, click the drop-down menu and navigate to the relationship or class where the property is located.
To avoid an error report, you should not navigate through a relationship marked with "*" in the
navigation tool.
6. Set the Filter Property to a domain property. For example, Gender.
7. In the Visibility Entries list, add values of this domain property for which the decorator should be visible.
For example, Male.
8. Repeat the steps for each icon.
9. Transform All Templates, build and run, and open a test diagram.
10. When you change the controlling property value, the decorators should appear and disappear.
Frequently, you want visibility to be controlled by a more complex formula than a simple set of values. For
example, to have an icon depend on the number of links of a particular type, or to make it depend on a
whether a number is in a particular range. In that case, use the following procedure.
To control the visibility of a decorator based on a formula
1. Add a calculated domain property to the domain class. In the Properties window, set the following values:
IsBrowsable = False - this hides the property from the user
Kind = Calculated - this means that you will provide code that calculates its value
Name for example DecoratorControl
Type = Boolean

For more information, see Calculated and Custom Storage Properties.


2. Make the new property control the decorator visibility.
a. Select the diagram element map, which is the gray line from the domain class to the shape. In the DSL
Details window, open the DecoratorMap tab.
b. Check the Visibility Filter box.
c. In Filter Property, select the control property DecoratorControl.
d. Under Visibility Entries, enter True .
3. Click Transform All Templates in the Solution Explorer toolbar.
4. Click Build Solution on the Build menu.
5. Double-click the error report that has appeared: "YourClass does not contain a definition for
GetDecoratorControlValue ...".
The text editor opens on Dsl\GeneratedCode\DomainClasses.cs. Above the highlighted error is a comment
that requests you to add a method.
6. Note the namespace, class and method that are missing. For example,
Company.FamilyTree.Person.GetDecoratorControlValue().
7. In a separate code file, write a partial class definition that contains the missing method. For example:

namespace Company.FamilyTree
{ partial class Person
{ bool GetDecoratorControlValue()
{
return this.Children.Count > 0;
} } }

For more information about customizing the model with program code, see Navigating and Updating a
Model in Program Code.
8. Rebuild and run the solution.

See Also
Defining Shapes and Connectors
Setting a Background Image on a Diagram
Navigating and Updating a Model in Program Code
Writing Code to Customise a Domain-Specific Language
Customizing Text and Image Fields
10/18/2017 8 min to read Edit Online

When you define a text decorator in a shape, it is represented by a TextField. For examples of the initialization of
TextFields and other ShapeFields, inspect Dsl\GeneratedCode\Shapes.cs in your DSL solution.
A TextField is an object that manages an area within a shape, such as the space assigned to a label. One TextField
instance is shared between many shapes of the same class. The TextField instance does not store the text of the
label separately for each instance: instead, the GetDisplayText(ShapeElement) method takes the shape as a
parameter, and can look up the text dependent on the current state of the shape and its model element.

How the appearance of a text field is determined


The DoPaint() method is called to displays the field on the screen. You can either override the default DoPaint(),
or you can override some of the methods that it calls. The following simplified version of the default methods can
help you understand how to override the default behavior:
// Simplified version:
public override void DoPaint(DiagramPaintEventArgs e, ShapeElement parentShape)
{
string text = GetDisplayText(shape);
StringFormat format = GetStringFormat(parentShape);
Brush brush = GetTextBrush(e.View, shape);
using (Font font = GetFont(shape))
{
e.Graphics.DrawString(text, font, brush, format);
}
}
// StringFormat determines whether the string is centered etc.
// To customize statically for all instances of this shape field,
// assign to DefaultStringFormat.
// To customize dynamically or per shape, override this:
public virtual StringFormat GetStringFormat(ShapeElement shape)
{ return DefaultStringFormat; }

// Override to customize the displayed string:


public virtual string GetDisplayText(ShapeElement shape)
{ return this.GetValue(shape).ToString(); }

// Brush determines the text color.


// To change the brush for every field, change the shape's styleset.
// To customize to a brush in the style set, override GetTextBrushId.
// To change the brush to non-standard color, override this.
// Should take account of whether selected.
public virtual Brush GetTextBrush(DiagramClientView view, ShapeElement shape)
{ return shape.StyleSet.GetBrush(this.GetTextBrushId(view, shape)); }

// Brush ID selects a brush from a StyleSet.


// Either return a member of DiagramBrushes
// or add your own brush to the shape or application's styleset.
// Override this to change dynamically or per instance.
// To change statically, just assign to default values.
public virtual StyleSetResourceId GetTextBrushId(DiagramClientView view, ShapeElement shape)
{ return IsSelected(view, shape) ? (view.Focused ? DefaultSelectedTextBrushId
: DefaultInactiveSelectedTextBrushId ) : DefaultTextBrushId ;
}

// Font determines the shape and size of the text.


// To change the font for every field, change the shape's styleset.
// To customize to a font in the style set, override GetFontId.
// To change the font to a non-standard font, override this.
public virtual Font GetFont(ShapeElement shape)
{ return shape.StyleSet.GetFont(GetFontId(shape)); }

// Selects a font from a styleset.


// Either return a member of DiagramFonts or
// add your own font to the shape or application's styleset.
// To change statically for all instances of this field,
// assign to DefaultFontId.
// To change per shape or dynamically, override this.
public virtual StyleSetResourceId GetFontId(ShapeElement parentShape)
{ return DefaultFontId; }

There are several other pairs of Getmethods and Default properties, such as
DefaultMultipleLine/GetMultipleLine() . You can assign a value to the Default property to change the value for all
instances of the shape field. To make the value vary from one shape instance to another, or dependent on the state
of the shape or its model element, override the Get method.

Static customizations
If you want to change every instance of this shape field, first find out whether you can set the property in the DSL
Definition. For example, you can set font size and style in the Properties window.
If not, then override the InitializeShapeFields method of your shape class, and assign a value to the appropriate
Default... property of the text field.

WARNING
To override InitializeShapeFields() , you must set the Generates Double Derived property of the shape class to
true in the DSL Definition.

In this example, a shape has a text field that will be used for user comments. We want to use the standard comment
font. Because it is a standard font from the style set, we can set the default font id:

partial class ExampleShape


{ protected override void InitializeShapeFields(IList<ShapeField> shapeFields)
{
// Fields set up according to DSL Definition:
base.InitializeShapeFields(shapeFields);
// Find and update comment field:
TextField commentField = ShapeElement.FindShapeField(shapeFields, "CommentDecorator") as TextField;
// Use the standard font for comments:
commentField.DefaultFontId = DiagramFonts.CommentText;

Dynamic customizations
To make the appearance vary dependent on the state of a shape or its model element, derive your own subclass of
TextField and override one or more Get... methods. You must also override your shape's InitializeShapeFields
method, and replace the instance of the TextField with an instance of your own class.
The following example makes the font of a text field dependent on the state of a Boolean domain property of the
shape's model element.
To run this example code, create a new DSL solution using the Minimal Language template. Add a Boolean domain
property AlternateState to the ExampleElement domain class. Add an icon decorator to the ExampleShape class,
and set its image to a bitmap file. Click Transform All Templates. Add a new code file in the DSL project, and
insert the following code.
To test the code, press F5 and, in the debugging solution, open a sample diagram. The default state of the icon
should appear. Select the shape and in the Properties window, change the value of the AlternateState property.
The font of the element name should change.
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
...

partial class ExampleShape


{
/// <summary>
/// Compose a list of the fields in this shape.
/// Called once for each shape class.
/// </summary>
protected override void InitializeShapeFields(IList<ShapeField> shapeFields)
{
// Fields set up according to DSL Definition:
base.InitializeShapeFields(shapeFields);
// Replace the text field for NameDecorator:
TextField oldField = ShapeElement.FindShapeField(shapeFields, "NameDecorator") as TextField;
shapeFields.Remove(oldField);
// Replace with my text field based on DSL Definition values:
MyTextField newField = new MyTextField(oldField);
shapeFields.Add(newField);
}
}
/// <summary>
/// Dynamic font depends on state of model element.
/// </summary>
public class MyTextField : TextField
{
public MyTextField(TextField prototype)
: base(prototype.Name)
{
DefaultText = prototype.DefaultText;
DefaultFocusable = prototype.DefaultFocusable;
DefaultAutoSize = prototype.DefaultAutoSize;
AnchoringBehavior.MinimumHeightInLines = prototype.AnchoringBehavior.MinimumHeightInLines;
AnchoringBehavior.MinimumWidthInCharacters = prototype.AnchoringBehavior.MinimumWidthInCharacters;
DefaultAccessibleState = prototype.DefaultAccessibleState;
}

public override System.Drawing.Font GetFont(ShapeElement parentShape)


{
// Access the Boolean domain property of the model element:
if ((parentShape.ModelElement as ExampleElement).AlternateState)
return new System.Drawing.Font("Callisto", 14.0f,
System.Drawing.FontStyle.Italic |
System.Drawing.FontStyle.Bold);
else
return base.GetFont(parentShape);
}

Style sets
The preceding example shows how you can change the text field to any font that is available. However, a preferable
method is to change it to one of a set of styles that is associated with the shape or with the application. To do this,
you override GetFontId or GetTextBrushId().
Alternatively, consider changing the style set of your shape by overriding InitializeResources. This has the effect of
changing the fonts and brushes for all of the shape fields.

Customizing Image Fields


When you define an image decorator in a shape, and when you define an image shape, the area in which the shape
is displayed is managed by an ImageField. For examples of the initialization of ImageFields and other ShapeFields,
inspect Dsl\GeneratedCode\Shapes.cs in your DSL solution.
An ImageField is an object that manages an area within a shape, such as the space assigned to a decorator. One
ImageField instance is shared between many shapes of the same shape class. The ImageField instance does not
store a separate image for each shape: instead, the GetDisplayImage(ShapeElement) method takes the shape as a
parameter, and can look up the image dependent on the current state of the shape and its model element.
If you want special behavior such as a variable image, you can create your own class derived from ImageField.
To create a subclass of ImageField
1. Set the Generates Double Derived property of the parent shape class in your DSL Definition.
2. Override the InitializeShapeFields method of your shape class.
Create a new code file in the DSL project, and write a partial class definition for the shape class. Override
the method definition there.
3. Inspect the code of InitializeShapeFields in DSL\GeneratedCode\Shapes.cs.
In your override method, call the base method and then create an instance of your own image field class.
Use this to replace the regular image field in the shapeFields list.

Dynamic icons
This example makes an icon change dependent on the state of the shape's model element.

WARNING
This example demonstrates how to make a dynamic image decorator. But if you only want to switch between one or two
images depending on the state of a model variable, it is simpler to create several image decorators, locate them in the same
position on the shape, and then set the Visibility filter to depend on specific values of the model variable. To set this filter,
select the shape map in the DSL Definition, open the DSL Details window, and click the Decorators tab.

To run this example code, create a new DSL solution using the Minimal Language template. Add a Boolean domain
property AlternateState to the ExampleElement domain class. Add an icon decorator to the ExampleShape class,
and set its image to a bitmap file. Click Transform All Templates. Add a new code file in the DSL project, and
insert the following code.
To test the code, press F5 and, in the debugging solution, open a sample diagram. The default state of the icon
should appear. Select the shape and in the Properties window, change the value of the AlternateState property.
The icon should then appear rotated through 90 degrees, on that shape.
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
...
partial class ExampleShape
{
/// <summary>
/// Compose a list of the fields in this shape.
/// Called once for each shape class.
/// </summary>
/// <param name="shapeFields"></param>
protected override void InitializeShapeFields(IList<ShapeField> shapeFields)
{
// Fields set up according to DSL Definition:
base.InitializeShapeFields(shapeFields);

// Replace the image field:


ShapeField oldField = ShapeElement.FindShapeField(shapeFields, "IconDecorator");
shapeFields.Remove(oldField);
// Must keep the same name:
MyImageField newField = new MyImageField(oldField.Name);
shapeFields.Add(newField);
newField.DefaultImage = (oldField as ImageField).DefaultImage.Clone() as System.Drawing.Image;
}
}

public class MyImageField : ImageField


{
public MyImageField(string tag) : base(tag) { }

/// <summary>
/// Get the image for this field in the given shape.
/// </summary>
public override System.Drawing.Image GetDisplayImage(ShapeElement parentShape)
{
ExampleElement element = parentShape.ModelElement as ExampleElement;
if (element.AlternateState == true)
return AlternateImage;
else
return base.GetDisplayImage(parentShape);
}

private System.Drawing.Image alternateImage;


public System.Drawing.Image AlternateImage
{
get
{
if (alternateImage == null)
{
// Alternate image is a copy of the default, rotated by 90 degrees:
alternateImage = this.DefaultImage.Clone() as System.Drawing.Image;
alternateImage.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
}
return alternateImage;
}
}
}
}

See Also
Defining Shapes and Connectors
Setting a Background Image on a Diagram
Navigating and Updating a Model in Program Code
Writing Code to Customise a Domain-Specific Language
Setting a Background Image on a Diagram
10/18/2017 2 min to read Edit Online

In Visual Studio Visualization and Modeling SDK, you can set the background image for a generated designer by
using custom code.

Setting the background image


To set a background image for a generated designer
1. Copy the image file that you want to use as the diagram's background into the Dsl\Resources directory for
the current project.
2. In Solution Explorer, right-click the Dsl\Resources folder, point to Add, and then click Existing Item.
3. In the Add Existing Item dialog box, browse to the Dsl\Resources folder.
4. In the Files of type list, click Image Files.
5. Click the image file that you copied to the directory, and then click Add.
6. Right-click Dsl, and click Properties to open the properties of the Dsl project.
7. On the Resources tab, click This project does not contain a default resources file. Click here to create
one.
8. Add the image file to the resource file by dragging the picture from Solution Explorer into the resources
window.
9. Open the File menu, and click the option to save the project properties.
10. Verify that the file Dsl\Properties\Resources.resx exists and has the file Resources.Designer.cs under it.
11. If Resources.Designer.cs is missing, click the file Resources.resx in Solution Explorer.
12. In the Properties window, set the Custom Tool property to ResXFileCodeGenerator .
13. In Solution Explorer, right-click the Dsl project, point to Add, and click New Folder.
14. Name the folder Custom.
15. Right-click the Custom folder, point to Add, and click New Item.
16. In the Add New Item dialog box, in the Templates list, click Code File.
17. In the Name box, type BackgroundImage.cs , and click Add.
18. Copy the following code to the BackgroundImage.cs file, adjusting namespace, diagram class name, and
image file resource name.
Replace "MyDiagramClass" with the name of the diagram partial class that is defined in
Dsl\GeneratedCode\Diagrams.cs. You can also retrieve the correct namespace from the file
Dsl\GeneratedCode\Diagrams.cs.
using System;
using Microsoft.VisualStudio.Modeling.Diagrams;

// Fix the namespace:


namespace Fabrikam.MyLanguage
{
// Fix the Diagram Class name - get it from GeneratedCode\Diagram.cs

public partial class Language29Diagram


{
protected override void InitializeInstanceResources()
{
// Fix the Resources namespace and the Image resource name:
ImageField backgroundField = new ImageField("background",
Fabrikam.MyLanguage.Properties.Resources.MyPicture);

backgroundField.DefaultFocusable = false;
backgroundField.DefaultSelectable = false;
backgroundField.DefaultVisibility = true;
backgroundField.DefaultUnscaled = false;

shapeFields.Add(backgroundField);

backgroundField.AnchoringBehavior
.SetTopAnchor(AnchoringBehavior.Edge.Top, 0.01);
backgroundField.AnchoringBehavior
.SetLeftAnchor(AnchoringBehavior.Edge.Left, 0.01);
backgroundField.AnchoringBehavior
.SetRightAnchor(AnchoringBehavior.Edge.Right, 0.01);
backgroundField.AnchoringBehavior
.SetBottomAnchor(AnchoringBehavior.Edge.Bottom, 0.01);

base.InitializeInstanceResources();
}
}
}

For more information about customizing the model with program code, see Navigating and Updating a
Model in Program Code.

See Also
Defining Shapes and Connectors
Customizing Text and Image Fields
Navigating and Updating a Model in Program Code
Writing Code to Customise a Domain-Specific Language

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK are
installed automatically when you install specific features of Visual Studio. For more details, see this blog post.
Nesting Shapes
10/18/2017 1 min to read Edit Online

See Jean-Marc Prieur's blog


Embedding a Diagram in a Windows Form
10/18/2017 2 min to read Edit Online

You can embed a DSL diagram in a Windows Control, which appears in the Visual Studio window.

Embedding a Diagram
To embed a DSL diagram in a Windows Control
1. Add a new User Control file to the DslPackage project.
2. Add a Panel control to the User Control. This panel will contain the DSL Diagram.
Add other controls that you require.
Set the Anchor properties of the controls.
3. In Solution Explorer, right-click the user control file and click View Code. Add this constructor and variable
to the code:

internal UserControl1(MyDSLDocView docView, Control content)


: this()
{
panel1.Controls.Add(content);
this.docView = docView;
}
private MyDSLDSLDocView docView;

4. Add a new file to the DslPackage project, with the following content:

using System.Windows.Forms;
namespace Company.MyDSL
{
partial class MyDSLDocView
{
private UserControl1 container;
public override IWin32Window Window
{
get
{
if (container == null)
{
// Put our own form inside the DSL window:
container = new UserControl1(this,
(Control)base.Window);
}
return container;
} } } }

5. To test the DSL, press F5 and open a sample model file. The diagram appears inside the control. The toolbox
and other features work normally.
Updating the Form using Store Events
1. In the form designer, add a ListBox named listBox1 . This will display a list of the elements in the model. It
will be kept in synchronism with the model using store events. For more information, see Event Handlers
Propagate Changes Outside the Model.
2. In the custom code file, override further methods to the DocView class:

partial class MyDSLDocView


{
/// <summary>
/// Register store event listeners.
/// This method is called when the model and diagram
/// have completed loading.
/// </summary>
protected override bool LoadView()
{
bool result = base.LoadView();
Store store = this.DocData.Store;
EventManagerDirectory emd = store.EventManagerDirectory;
DomainClassInfo componentClass = store.DomainDataDirectory.FindDomainClass(typeof(ExampleElement));
emd.ElementAdded.Add(componentClass, new EventHandler<ElementAddedEventArgs>(AddElement));
emd.ElementDeleted.Add(componentClass, new EventHandler<ElementDeletedEventArgs>(RemoveElement));

// Do the initial parts list:


container.SetUpFormFromModel();
return result;
}
/// <summary>
/// Listener method called on creation of each instance of
/// the ExampleElement class or its subclasses.
/// </summary>
private void AddElement(object sender, ElementAddedEventArgs e)
{
container.Add(e.ModelElement as ExampleElement);
}
/// <summary>
/// Listener method called after deletion of each instance of
/// the ExampleElement class or its subclasses.
/// </summary>
private void RemoveElement(object sender, ElementDeletedEventArgs e)
{
container.Remove(e.ModelElement as ExampleElement);
}

3. In the code behind the user control, insert methods to listen for elements added and removed:
public partial class UserControl1 : UserControl { ...

private ExampleModel modelRoot;

internal void Add(ExampleElement e) { UpdatePartsList(); }


internal void Remove(ExampleElement e) { UpdatePartsList(); }

internal void SetUpFormFromModel()


{
modelRoot = this.docView.CurrentDiagram.ModelElement as ExampleModel;
UpdatePartsList();
}

private void UpdatePartsList()


{
StringBuilder builder = new StringBuilder();
listBox1.Items.Clear();
foreach (ExampleElement c in modelRoot.Elements)
{
listBox1.Items.Add(c.Name);
}
}

4. To test the DSL, press F5 and in the experimental instance of Visual Studio, open a sample model file.
Notice that the list box shows a list of the elements in the model, and that it is correct after any addition or
deletion, and after Undo and Redo.

See Also
Navigating and Updating a Model in Program Code
Writing Code to Customise a Domain-Specific Language
Customizing Tools and the Toolbox
10/18/2017 12 min to read Edit Online

You must define toolbox items for the elements that you want to let users add to their models. There are two kinds
of tools: element tools and connection tools. In the generated designer, a user can select an element tool to drag
shapes to the diagram, and can select a connection tool to draw links between the shapes. In general, element tools
let users add instances of domain classes to their models, and connection tools let them add instances of domain
relationships.
In this topic:
How the Toolbox is Defined
Customizing Element Tools
Creating Groups of Elements from a Tool
Customizing Connection Tools

How the toolbox is defined


In the DSL Explorer, expand the Editor node and the nodes underneath it. Typically you will see a hierarchy that
resembles this:

Editor
Toobox Tabs
MyDsl //a tab
Tools
ExampleElement // an element tool
ExampleRelationship // a connection tool

In this part of DSL Explorer, you can:


Create new tabs. Tabs define the section headings in the toolbox.
Create new tools.
Copy and paste tools.
Move tools up or down in the list.
Delete tabs and tools.

IMPORTANT
To add or paste items in a DSL Explorer, right-click the grandparent of the new node. For example, to add a tool, right-click
the tab, and not the Tools node. To add a tab, right-click the Editor node.

The Toolbox Icon property of every tool references a 16x16 bitmap file. These files are usually kept in the
Dsl\Resources folder.
The Class property of an element tool refers to a concrete domain class. By default, the tool will create instances of
this class. However, you can write code to have the tool create groups of elements, or elements of different types.
The Connection Builder property of a connection tool refers to a connection builder, which defines what types of
elements the tool can connect, and what relationships it creates between them. Connection builders are defined as
nodes in the DSL Explorer. Connection builders are created automatically when you define domain relationships,
but you can write code to customize them.
To add a tool to the toolbox
1. You usually create an element tool after you have created a shape class and mapped it to a domain class.
You usually create a connector tool after you have created a connector class and mapped it to a reference
relationship.
2. In DSL Explorer, expand the Editor node and the Toolbox Tabs node.
Right-click a toolbox tab node, and then click Add New Element Tool or Add New Connection Tool.
3. Set the Toolbox Icon property to refer to a 16x16 bitmap.
If you want to define a new icon, create a bitmap file in Solution Explorer in the Dsl\Resources folder. The
file should have the following property values: Build Action = Content; Copy to Output Directory = Do
not copy.
4. For an element tool: Set the Class property of the tool to refer to a concrete domain class that is mapped
to a shape.
For a connector tool: Set the Connection Builder property of the tool to one of the items that are offered
in the drop-down list. Connection builders are automatically created when you map a connector to a
domain relationship. If you have recently created a connector, you would normally select the associated
connection builder.
5. To test the DSL, press F5 or CTRL+F5, and in the experimental instance of Visual Studio, open a sample
model file. The new tool should appear on the toolbox. Drag it onto the diagram to verify that it creates a
new element.
If the tool does not appear, stop the experimental Visual Studio. In the Windows Start menu, run Reset the
Microsoft Visual Studio 2010 Experimental Instance. On the Visual StudioBuild menu, click Rebuild
Solution. Then test the DSL again.

Customizing Element Tools


By default, the tool will create a single instance of the specified class, but you can vary this in two ways:
Define Element Merge Directives on other classes, enabling them to accept new instances of this class, and
enabling them to create additional links when the new element is created. For example, you could allow the
user to drop a Comment onto another element, and thereby create a reference link between the two.
These customizations also affect what happens when the user pastes or drags and drops an element.
For more information, see Customizing Element Creation and Movement.
Write code to customize the tool so that it can create groups of elements. The tool is initialized by methods
in ToolboxHelper.cs that you can override. For more information, see Creating Groups of Elements from a
Tool.

Creating Groups of Elements from a Tool


Each element tool contains a prototype of the elements that it should create. By default, each element tool creates a
single element, but it is also possible to create a group of related objects with one tool. To do this, you initialize the
tool with an ElementGroupPrototype that contains the related items.
The following example is taken from a DSL in which there is a type Transistor. Each Transistor has three named
Terminals. The element tool for Transistors stores a prototype containing four model elements and three
relationship links. When the user drags the tool onto the diagram, the prototype is instantiated and linked to the
model root.
This code overrides a method that is defined in Dsl\GeneratedCode\ToolboxHelper.cs.
For more information about customizing the model by using program code, see Navigating and Updating a Model
in Program Code.

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

public partial class CircuitsToolboxHelper


{
/// <summary>
/// Toolbox initialization, called for each element tool on the toolbox.
/// This version deals with each Component subtype separately.
/// </summary>
/// <param name="store"></param>
/// <param name="domainClassId">Identifies the domain class this tool should instantiate.</param>
/// <returns>prototype of the object or group of objects to be created by tool</returns>
protected override ElementGroupPrototype CreateElementToolPrototype(Store store, Guid domainClassId)
{
if (domainClassId == Transistor.DomainClassId)
{
Transistor transistor = new Transistor(store);

transistor.Base = new ComponentTerminal(store);


transistor.Collector = new ComponentTerminal(store);
transistor.Emitter = new ComponentTerminal(store);

transistor.Base.Name = "base";
transistor.Collector.Name = "collector";
transistor.Emitter.Name = "emitter";

// Create an ElementGroup for the Toolbox.


ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
elementGroup.AddGraph(transistor, true);
// AddGraph includes the embedded parts

return elementGroup.CreatePrototype();
}
else
{
return base.CreateElementToolPrototype(store, domainClassId);
} } }

Customizing Connection Tools


Usually, you create an element tool when you create a new connector class. Alternatively, you can overload one
tool by allowing the types of the two ends to determine the type of the relationship. For example, you could define
one connection tool that could create both Person-Person relationships and Person-Town relationships.
Connection tools invoke connection builders. Use connection builders to specify how users can link elements in the
generated designer. Connection builders specify the elements that can be linked and the kind of link that is created
between them.
When you create a reference relationship between domain classes, a connection builder is automatically created.
You can use this connection builder when you map a connection tool. For more information about how to create
connection tools, see Configuring the Toolbox.
You can modify the default connection builder so that it can deal with a different range of source and target types,
and create different types of relationship.
You also can write custom code for connection builders to specify the source and target classes for the connection,
define the type of connection to be made, and take other actions associated with the creation of a connection.
The Structure of Connection Builders
Connection builders contain one or more link connect directives, which specify the domain relationship and the
source and target elements. For example, in the Task Flow solution template, you can see the
CommentReferencesSubjectsBuilder in the DSL Explorer. This connection builder contains one link connect
directive named CommentReferencesSubjects, which is mapped to the domain relationship
CommentReferencesSubjects. This link connect directive contains a source role directive that points to the
Comment domain class, and a target role directive that points to the FlowElement domain class.

Using Connection Builders to Restrict Source and Target Roles


You can use connection builders to restrict the occurrence of certain classes in either the source role or the target
role of a given domain relationship. For example, you may have a base domain class that has a domain
relationship to another domain class, but you may not want all derived classes of the base class to have the same
roles in that relationship. In the Task Flow solution, there are four concrete domain classes (StartPoint, EndPoint,
MergeBranch, and Synchronization) that inherit directly from the abstract domain class FlowElement, and two
concrete domain classes (Task and ObjectInState) that inherit indirectly from it. There is also a Flow reference
relationship that takes FlowElement domain classes in both its source role and target role. However, an instance
of an EndPoint domain class should not be the source of an instance of a Flow relationship, nor should an
instance of a StartPoint class be the target of an instance of a Flow relationship. The FlowBuilder connection
builder has a link connect directive named Flow that specifies which domain classes can play the source role (Task,
MergeBranch, StartPoint, and Synchronization) and which can play the target role(MergeBranch, Endpoint,
and Synchronization).
Connection Builders with Multiple Link Connect Directives
You can add more than one link connect directive to a connection builder. This can help you hide some of the
complexities of the domain model from users and keep the Toolbox from getting too cluttered. You can add link
connect directives for several different domain relationships to a single connection builder. However, you should
combine domain relationships when they perform approximately the same function.
In the Task Flow solution, the Flow connection tool is used to draw instances of both the Flow and the
ObjectFlow domain relationships. The FlowBuilder connection builder has, in addition to the Flow link connect
directive described earlier, two link connect directives named ObjectFlow. These directives specify that an instance
of an ObjectFlow relationship may be drawn between instances of the ObjectInState domain class, or from an
instance of an ObjectInState to an instance of a Task, but not between two instances of a Task, or from an
instance of a Task to an instance of an ObjectInState. However, an instance of a Flow relationship may be drawn
between two instances of a Task. If you compile and run the Task Flow solution, you can see that drawing a Flow
from an instance of an ObjectInState to an instance of a Task creates an instance of an ObjectFlow, but drawing
a Flow between two instances of a Task creates an instance of a Flow.
Custom Code for Connection Builders
There are four checkboxes in the user interface that define different types of customization of connection builders:
the Custom accept check box on a source or target role directive
the Custom connect check box on a source or target role directive
the Uses custom connect check box on a connect directive
the Is Custom property of the connection builder
You have to provide some program code to make these customizations. To discover what code you must
supply, check one of these boxes, click Transform All Templates, and then build your solution. An error
report will result. Double-click the error report to see a comment that explains what code you should add.

NOTE
To add custom code, create a partial class definition in a code file separate from the code files in the GeneratedCode folders.
To avoid losing your work, you should not edit the generated code files. For more information, see Overriding and Extending
the Generated Classes.

Creating Custom Connection code


In each link connect directive, the Source role directives tab defines from what types you can drag. Similarly, the
Target role directives tab defines to what types you can drag. For each type, you can further specify whether to
allow the connection (for that link connect directive) by setting the Custom Accept flag and then supplying the
extra code.
You can also customize what occurs when the connection is made. For example, you can customize just the case
where the drag occurs to or from a particular class, all the cases that one link connect directive governs, or the
whole FlowBuilder connection builder. For each of these options, you can set custom flags at the appropriate level.
When you transform all templates and try to build the solution, error messages direct you to comments that are in
the generated code. These comments identify what you must supply.
In the Components Diagram sample, the connection builder for the Connection domain relationship is customized
to restrict the connections that can be made between ports. The following illustration shows that you can make
connections only from OutPort elements to InPort elements, but you can nest components inside each other.
Connection Coming in to an OutPort from a Nested Component

Therefore, you might want to specify that a connection can come from a nested component to an OutPort. To
specify such a connection, you set Uses Custom Accept on the InPort type as source role and the OutPort type
as target role in the DSL Details window as shown in the following illustrations:
Link Connect Directive in DSL Explorer

Link Connect Directive in DSL Details Window


You must then provide methods in the ConnectionBuilder class:

public partial class ConnectionBuilder


{
/// <summary>
/// OK if this component has children
/// </summary>
private static bool CanAcceptInPortAsSource(InPort candidate)
{
return candidate.Component.Children.Count > 0;
}

/// <summary>
/// Only if source is on parent of target.
/// </summary>
private static bool CanAcceptInPortAndInPortAsSourceAndTarget (InPort sourceInPort, InPort
targetInPort)
{
return sourceInPort.Component == targetInPort.Component.Parent;
}
// And similar for OutPorts...

For more information about customizing the model by using program code, see Navigating and Updating a Model
in Program Code.
You can use similar code, for example, to prevent users from creating loops with parent-child links. These
restrictions are considered 'hard' constraints because users cannot violate them at any time. You can also create
'soft' validation checks that users can bypass temporarily by creating invalid configurations that they cannot save.
Good Practice in Defining Connection Builders
You should define one connection builder to create different types of relationships only if they are conceptually
related. In the task flow sample, you use the same builder to create flows between tasks and also between tasks
and objects. However, it would be confusing to use the same builder to create relationships between comments
and tasks.
If you define a connection builder for multiple types of relationships, you should ensure that it cannot match more
than one type from the same pair of source and target objects. Otherwise, the results will be unpredictable.
You use custom code to apply 'hard' constraints, but you should consider whether users should be able to
temporarily make invalid connections. If they should, you can modify the constraints so that connections are not
validated until users try to save changes.

See Also
Customizing Element Creation and Movement
Customizing Copy Behavior
How to: Add a Drag-and-Drop Handler
Navigating and Updating a Model in Program Code
Circuit Diagrams sample DSL
Customizing Element Creation and Movement
10/18/2017 14 min to read Edit Online

You can allow an element to be dragged onto another, either from the toolbox or in a paste or move operation.
You can have the moved elements linked to the target elements, using the relationships that you specify.
An element merge directive (EMD) specifies what happens when one model element is merged into another
model element. This happens when:
The user drags from the toolbox onto the diagram or a shape.
The user creates an element by using an Add menu in the explorer or a compartment shape.
The user moves an item from one swimlane to another.
The user pastes an element.
Your program code calls the element merge directive.
Although the creation operations might seem to be different from the copy operations, they actually work
in the same way. When an element is added, for example from the toolbox, a prototype of it is replicated.
The prototype is merged into the model in the same manner as elements that have been copied from
another part of the model.
The responsibility of an EMD is to decide how an object or group of objects should be merged into a
particular location in the model. In particular, it decides what relationships should be instantiated to link
the merged group into the model. You can also customize it to set properties and to create additional
objects.

The role of an Element Merge Directive


An EMD is generated automatically when you define an embedding relationship. This default EMD creates
an instance of the relationship when users add new child instances to the parent. You can modify these
default EMDs, for example by adding custom code.
You can also add your own EMDs in the DSL definition, to let users drag or paste different combinations of
merged and receiving classes.
Defining an Element Merge Directive
You can add element merge directives to domain classes, domain relationships, shapes, connectors, and
diagrams. You can add or find them in DSL Explorer under the receiving domain class. The receiving class is the
domain class of the element that is already in the model, and onto which the new or copied element will be
merged.

The Indexing Class is the domain class of elements that can be merged into members of the receiving class.
Instances of subclasses of the Indexing Class will also be merged by this EMD, unless you set Applies to
subclasses to False.
There are two kinds of merge directive:
A Process Merge directive specifies the relationships by which the new element should be linked into the
tree.
A Forward Merge directive redirects the new element to another receiving element, typically a parent.
You can add custom code to merge directives:
Set Uses custom accept to add your own code to determine whether a particular instance of the indexing
element should be merged into the target element. When the user drags from the toolbox, the "invalid"
pointer shows if your code disallows the merge.
For example, you could allow the merge only when the receiving element is in a particular state.
Set Uses custom merge to add provide own code to define the changes that are made to the model when
the merge is performed.
For example, you could set properties in the merged element by using data from its new location in the
model.

NOTE
If you write custom merge code, it affects only merges that are performed by using this EMD. If there are other EMDs that
merge the same type of object, or if there is other custom code that creates these objects without using the EMD, then
they will not be affected by your custom merge code.
If you want to make sure that a new element or new relationship is always processed by your custom code, consider
defining an AddRule on the embedding relationship and a DeleteRule on the element's domain class. For more
information, see Rules Propagate Changes Within the Model.

Example: Defining an EMD without custom code


The following example lets users create an element and a connector at the same time by dragging from the
toolbox onto an existing shape. The example adds an EMD to the DSL Definition. Before this modification, users
can drag tools onto the diagram, but not onto existing shapes.
Users can also paste elements onto other elements.
To let users create an element and a connector at the same time
1. Create a new DSL by using the Minimal Language solution template.
When you run this DSL, it lets you create shapes and connectors between the shapes. You cannot drag a
new ExampleElement shape from the toolbox onto an existing shape.
2. To let users merge elements onto ExampleElement shapes, create a new EMD in the ExampleElement
domain class:
a. In DSL Explorer, expand Domain Classes. Right-click ExampleElement and then click Add New
Element Merge Directive.
b. Make sure that the DSL Details window is open, so that you can see the details of the new EMD.
(Menu: View, Other Windows, DSL Details.)
3. Set the Indexing class in the DSL Details window, to define what class of elements can be merged onto
ExampleElement objects.

For this example, select ExampleElements , so that the user can drag new elements onto existing elements.
Notice that the Indexing class becomes the name of the EMD in DSL Explorer.
4. Under Process merge by creating links, add two paths:
a. One path links the new element to the parent model. The path expression that you need to enter
navigates from the existing element, up through the embedding relationship to the parent model.
Finally, it specifies the role in the new link to which the new element will be assigned. The path is as
follows:
ExampleModelHasElements.ExampleModel/!ExampleModel/.Elements

b. The other path links the new element to the existing element. The path expression specifies the
reference relationship and the role to which the new element will be assigned. This path is as
follows:
ExampleElementReferencesTargets.Sources

You can use the path navigation tool to create each path:
c. Under Process merge by creating links at paths, click <add path>.
d. Click the drop-down arrow to the right of the list item. A tree view appears.
e. Expand the nodes in the tree to form the path that you want to specify.
5. Test the DSL:
a. Press F5 to rebuild and run the solution.
Rebuilding will take longer than usual because the generated code will be updated from text
templates to conform to the new DSL Definition.
b. When the experimental instance of Visual Studio has started, open a model file of your DSL. Create
some example elements.
c. Drag from the Example Element tool onto an existing shape.
A new shape appears, and it is linked to the existing shape with a connector.
d. Copy an existing shape. Select another shape and paste.
A copy of the first shape is created. It has a new name and it is linked to the second shape with a
connector.
Notice the following points from this procedure:
By creating Element Merge Directives, you can allow any class of element to accept any other. The EMD is
created in the receiving domain class, and the accepted domain class is specified in the Index class field.
By defining paths, you can specify what links should be used to connect the new element to the existing
model.
The links that you specify should include one embedding relationship.
The EMD affects both creation from the toolbox and also paste operations.
If you write custom code that creates new elements, you can explicitly invoke the EMD by using the
ElementOperations.Merge method. This makes sure that your code links new elements into the model in the
same way as other operations. For more information, see Customizing Copy Behavior.

Example: Adding Custom Accept code to an EMD


By adding custom code to an EMD, you can define more complex merge behavior. This simple example prevents
the user from adding more than a fixed number of elements to the diagram. The example modifies the default
EMD that accompanies an embedding relationship.
To write Custom Accept code to restrict what the user can add
1. Create a DSL by using the Minimal Language solution template. Open the DSL Definition diagram.
2. In DSL Explorer, expand Domain Classes, ExampleModel , Element Merge Directives. Select the element
merge directive that is named ExampleElement .
This EMD controls how the user can create new ExampleElement objects in the model, for example by
dragging from the toolbox.
3. In the DSL Details window, select Uses custom accept.
4. Rebuild the solution. This will take longer than usual because the generated code will be updated from the
model.
A build error will be reported, similar to: "Company.ElementMergeSample.ExampleElement does not
contain a definition for CanMergeExampleElement..."
You must implement the method CanMergeExampleElement .
5. Create a new code file in the Dsl project. Replace its content with the following code and change the
namespace to the namespace of your project.
using Microsoft.VisualStudio.Modeling;

namespace Company.ElementMergeSample // EDIT.


{
partial class ExampleModel
{
/// <summary>
/// Called whenever an ExampleElement is to be merged into this ExampleModel.
/// This happens when the user pastes an ExampleElement
/// or drags from the toolbox.
/// Determines whether the merge is allowed.
/// </summary>
/// <param name="rootElement">The root element in the merging EGP.</param>
/// <param name="elementGroupPrototype">The EGP that the user wants to merge.</param>
/// <returns>True if the merge is allowed</returns>
private bool CanMergeExampleElement(ProtoElementBase rootElement, ElementGroupPrototype
elementGroupPrototype)
{
// Allow no more than 4 elements to be added:
return this.Elements.Count < 4;
}
}
}

This simple example restricts the number of elements that can be merged into the parent model. For more
interesting conditions, the method can inspect any of the properties and links of the receiving object. It can
also inspect the properties of the merging elements, which are carried in a ElementGroupPrototype. For
more information about ElementGroupPrototypes , see Customizing Copy Behavior. For more information
about how to write code that reads a model, see Navigating and Updating a Model in Program Code.
6. Test the DSL:
a. Press F5 to rebuild the solution. When the experimental instance of Visual Studio opens, open an
instance of your DSL.
b. Create new elements in several ways:
a. Drag from the Example Element tool onto the diagram.
b. In the Example Model Explorer, right-click the root node and then click Add New
Example Element.
c. Copy and paste an element on the diagram.
c. Verify that you cannot use any of these ways to add more than four elements to the model. This is
because they all use the Element Merge Directive.

Example: Adding Custom Merge code to an EMD


In custom merge code, you can define what happens when the user drags a tool or pastes onto an element. There
are two ways to define a custom merge:
1. Set Uses Custom Merge and supply the required code. Your code replaces the generated merge code.
Use this option if you want to completely redefine what the merge does.
2. Override the MergeRelate method, and optionally the MergeDisconnect method. To do this, you must set
the Generates Double Derived property of the domain class. Your code can call the generated merge
code in the base class. Use this option if you want to perform additional operations after the merge has
been performed.
These approaches only affect merges that are performed by using this EMD. If you want to affect all ways
in which the merged element can be created, an alternative is to define an AddRule on the embedding
relationship and a DeleteRule on the merged domain class. For more information, see Rules Propagate
Changes Within the Model.
To override MergeRelate
1. In the DSL definition, make sure that you have defined the EMD to which you want to add code. If you
want, you can add paths and define custom accept code as described in the previous sections.
2. In the DslDefinition diagram, select the receiving class of the merge. Typically it is the class at the source
end of an embedding relationship.
For example, in a DSL generated from the Minimal Language solution, select ExampleModel .
3. In the Properties window, set Generates Double Derived to true.
4. Rebuild the solution.
5. Inspect the content of Dsl\Generated Files\DomainClasses.cs. Search for methods named MergeRelate
and examine their contents. This will help you write your own versions.
6. In a new code file, write a partial class for the receiving class, and override the MergeRelate method.
Remember to call the base method. For example:

partial class ExampleModel


{
/// <summary>
/// Called when the user drags or pastes an ExampleElement onto the diagram.
/// Sets the time of day as the name.
/// </summary>
/// <param name="sourceElement">Element to be added</param>
/// <param name="elementGroup">Elements to be merged</param>
protected override void MergeRelate(ModelElement sourceElement, ElementGroup elementGroup)
{
// Connect the element according to the EMD:
base.MergeRelate(sourceElement, elementGroup);

// Custom actions:
ExampleElement mergingElement = sourceElement as ExampleElement;
if (mergingElement != null)
{
mergingElement.Name = DateTime.Now.ToLongTimeString();
}
}
}

To write Custom Merge code


1. In Dsl\Generated Code\DomainClasses.cs, inspect methods named MergeRelate . These methods create
links between a new element and the existing model.
Also, inspect methods named MergeDisconnect . These methods unlink an element from the model when it
is to be deleted.
2. In DSL Explorer, select or create the Element Merge Directive that you want to customize. In the DSL
Details window, set Uses Custom Merge.
When you set this option, the Process Merge and Forward Merge options are ignored. Your code is used
instead.
3. Rebuild the solution. It will take longer than usual because the generated code files will be updated from
the model.
Error messages will appear. Double-click the error messages to see the instructions in the generated code.
These instructions ask you to supply two methods, MergeRelate YourDomainClass and MergeDisconnect
YourDomainClass
4. Write the methods in a partial class definition in a separate code file. The examples you inspected earlier
should suggest what you need.
Custom merge code will not affect code that creates objects and relationships directly, and it will not affect
other EMDs. To make sure that your additional changes are implemented regardless of how the element is
created, consider writing an AddRule and a DeleteRule instead. For more information, see Rules
Propagate Changes Within the Model.

Redirecting a Merge Operation


A forward merge directive redirects the target of a merge operation. Typically, the new target is the embedding
parent of the initial target.
For example, in a DSL that was created with the component diagram template, Ports are embedded in
Components. Ports are displayed as small shapes on the edge of a component shape. The user creates ports by
dragging the Port tool onto a Component shape. But sometimes, the user mistakenly drags the Port tool onto an
existing port, instead of the component, and the operation fails. This is an easy mistake when there are several
existing ports. To help the user to avoid this nuisance, you can allow ports to be dragged onto an existing port, but
have the action redirected to the parent component. The operation works as if the target element were the
component.
You can create a forward merge directive in the Component Model solution. If you compile and run the original
solution, you should see that users can drag any number of Input Port or Output Port elements from the
Toolbox to a Component element. However, they cannot drag a port to an existing port. The Unavailable pointer
alerts them that this move is not enabled. However, you can create a forward merge directive so that a port that is
unintentionally dropped on an existing Input Port is forwarded to the Component element.
To create a forward merge directive
1. Create a Domain-Specific Language Tools solution by using the Component Model template.
2. Display the DSL Explorer by opening DslDefinition.dsl.
3. In the DSL Explorer, expand Domain Classes.
4. The ComponentPort abstract domain class is the base class of both InPort and OutPort. Right-click
ComponentPort and then click Add New Element Merge Directive.
A new Element Merge Directive node appears under the Element Merge Directives node.
5. Select the Element Merge Directive node and open the DSL Details window.
6. In the Indexing class list, select ComponentPort.
7. Select Forward merge to a different domain class.
8. In the path selection list, expand ComponentPort, expand ComponentHasPorts, and then select
Component.
The new path should resemble this one:
ComponentHasPorts.Component/!Component
9. Save the solution, and then transform the templates by clicking the rightmost button on the Solution
Explorer toolbar.
10. Build and run the solution. A new instance of Visual Studio appears.
11. In Solution Explorer, open Sample.mydsl. The diagram and the ComponentLanguage Toolbox appear.
12. Drag an Input Port from the Toolbox to another Input Port. Next, drag an OutputPort to an InputPort
and then to another OutputPort.
You should not see the Unavailable pointer, and you should be able to drop the new Input Port on the
existing one. Select the new Input Port and drag it to another point on the Component.

See Also
Navigating and Updating a Model in Program Code
Customizing Tools and the Toolbox
Circuit Diagrams sample DSL
Customizing Copy Behavior
10/18/2017 14 min to read Edit Online

In a domain-specific language (DSL) created with the Visual Studio Visualization and Modeling SDK, you can alter
what happens when the user copies and pastes elements.

Standard Copy and Paste Behavior


To enable copying, set the Enable Copy Paste property of the Editor node in DSL Explorer.
By default, when the user copies elements to the clipboard, the following elements are also copied:
Embedded descendants of the selected elements. (That is, elements that are the targets of embedding
relationships that are sourced at copied elements.)
Relationship links between the copied elements.
This rule applies recursively to the copied elements and links.

The copied elements and links are serialized and stored in an ElementGroupPrototype (EGP), which is
placed on the clipboard.
An image of the copied elements is also placed on the clipboard. This allows the user to paste into other
applications such as Word.
The user can paste copied elements onto a target that can accept the elements according to the DSL
Definition. For example, in a DSL generated from the components solution template, the user can paste
ports onto components, but not onto the diagram; and can paste components onto the diagram, but not
onto other components.

Customizing Copy and Paste Behavior


For more information about customizing the model by using program code, see Navigating and Updating a
Model in Program Code.
Enable or disable copy, cut, and paste.
In DSL Explorer, set the Enable Copy Paste property of the Editor node.
Copy links to the same target. For example, to have a copied comment box linked to the same subject element.
Set the Propagates Copy property of the role to Propagate copy to link only. For more information, see
Customizing Link Copy Behavior.
Copy linked elements. For example, when you copy a new element, copies of any linked comment boxes are
made as well.
Set the Propagates Copy property of the role to Propagate copy to link and opposite role player. For more
information, see Customizing Link Copy Behavior.
Rapidly duplicate elements by copying and pasting. Normally, the item you just copied is still selected, and
you cannot paste the same type of element onto it.
Add an Element Merge Directive to the domain class, and set it to forward merges to the parent class. This will
have the same effect on drag operations. For more information, see Customizing Element Creation and
Movement.
- or -
Select the diagram before pasting the elements, by overriding ClipboardCommandSet.ProcessOnPasteCommand() . Add
this code in a custom file in the DslPackage project:

namespace Company.MyDsl {
using System.Linq;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Shell;
partial class MyDslClipboardCommandSet
{
protected override void ProcessOnMenuPasteCommand()
{
// Deselect the current selection after copying:
Diagram diagram = (this.CurrentModelingDocView as SingleDiagramDocView).Diagram;
this.CurrentModelingDocView
.SelectObjects(1, new object[] { diagram }, 0);
}
} }

Create additional links when the user pastes onto a selected target. For example, when a comment box is
pasted onto an element, a link is made between them.
Add an Element Merge Directive to the target domain class, and set it to process the merge by adding links. This
will have the same effect on drag operations. For more information, see Customizing Element Creation and
Movement.
- or -
Override ClipboardCommandSet.ProcessOnPasteCommand() to create the additional links after calling the base
method.
Customize the formats in which elements can be copied to external applications - for example, to add a
border to the bitmap form.
Override MyDsl ClipboardCommandSet.ProcessOnMenuCopyCommand() in the DslPackage project.
Customize how elements are copied to the clipboard by the copy command, but not in a drag
operation.
Override MyDsl ClipboardCommandSet.CopyModelElementsIntoElementGroupPrototype() in the DslPackage project.
Preserve shape layout through copy and paste.
When the user copies multiple shapes, you can preserve their relative positions when they are pasted. This
technique is demonstrated by the example at VMSDK: Circuit Diagrams sample.
To achieve this effect, add the shapes and connectors to the copied ElementGroupPrototype. The most convenient
method to override is ElementOperations.CreateElementGroupPrototype(). To do this, add the following code to
the Dsl project:
public class MyElementOperations : DesignSurfaceElementOperations
{
// Create an EGP to add to the clipboard.
// Called when the elements to be copied have been
// collected into an ElementGroup.
protected override ElementGroupPrototype CreateElementGroupPrototype(ElementGroup elementGroup,
ICollection<ModelElement> elements, ClosureType closureType)
{
// Add the shapes and connectors:
// Get the elements already in the group:
ModelElement[] mels = elementGroup.ModelElements
.Concat(elementGroup.ElementLinks) // Omit if the paste target is not the diagram.
.ToArray();
// Get their shapes:
IEnumerable<PresentationElement> shapes =
mels.SelectMany(mel =>
PresentationViewsSubject.GetPresentation(mel));
elementGroup.AddRange(shapes);

return base.CreateElementGroupPrototype
(elementGroup, elements, closureType);
}

public MyElementOperations(IServiceProvider serviceProvider, ElementOps1Diagram diagram)


: base(serviceProvider, diagram)
{ }
}

// Replace the standard ElementOperations


// singleton with your own:
partial class MyDslDiagram // EDIT NAME
{
/// <summary>
/// Singleton ElementOperations attached to this diagram.
/// </summary>
public override DesignSurfaceElementOperations ElementOperations
{
get
{
if (singleton == null)
{
singleton = new MyElementOperations(this.Store as IServiceProvider, this);
}
return singleton;
}
}
private MyElementOperations singleton = null;
}

Paste shapes in a chosen location, such as the current cursor position.


When the user copies multiple shapes, you can preserve their relative positions when they are pasted. This
technique is demonstrated by the example at VMSDK: Circuit Diagrams sample.
To achieve this effect, override ClipboardCommandSet.ProcessOnMenuPasteCommand() to use the location-specific
version of ElementOperations.Merge() . To do this, add the following code in the DslPackage project:
partial class MyDslClipboardCommandSet // EDIT NAME
{
/// <summary>
/// This method assumes we only want to paste things onto the diagram
/// - not onto anything contained in the diagram.
/// The base method pastes in a free space on the diagram.
/// But if the menu was used to invoke paste, we want to paste in the cursor position.
/// </summary>
protected override void ProcessOnMenuPasteCommand()
{

NestedShapesSampleDocView docView = this.CurrentModelingDocView as NestedShapesSampleDocView;

// Retrieve data from clipboard:


System.Windows.Forms.IDataObject data = System.Windows.Forms.Clipboard.GetDataObject();

Diagram diagram = docView.CurrentDiagram;


if (diagram == null) return;

if (!docView.IsContextMenuShowing)
{
// User hit CTRL+V - just use base method.

// Deselect anything that's selected, otherwise


// pasted item will be incompatible:
if (!this.IsDiagramSelected())
{
docView.SelectObjects(1, new object[] { diagram }, 0);
}

// Paste into a convenient spare space on diagram:


base.ProcessOnMenuPasteCommand();
}
else
{
// User right-clicked - paste at mouse position.

// Utility class:
DesignSurfaceElementOperations op = diagram.ElementOperations;

ShapeElement pasteTarget = diagram;

// Check whether what's in the paste buffer is acceptable on the target.


if (pasteTarget != null && op.CanMerge(pasteTarget, data))
{

// Although op.Merge would be a no-op if CanMerge failed, we check CanMerge first


// so that we don't create an empty transaction (after which Undo would be no-op).
using (Transaction t = diagram.Store.TransactionManager.BeginTransaction("paste"))
{
PointD place = docView.ContextMenuMousePosition;
op.Merge(pasteTarget, data, PointD.ToPointF(place));
t.Commit();
}
}
}
}
}

Let the user drag and drop elements.


See How to: Add a Drag-and-Drop Handler.

Customizing Link Copy Behavior


When the user copies an element, the standard behavior is that any embedded elements are also copied. You can
modify the standard copying behavior. In the DSL Definition, select a role at one side of a relationship and in the
Properties window set the Propagates Copy value.

There are three values:


Do not propagate copy
Propagate copy to link only - when the group is pasted, the new copy of this link will refer to the existing
element at the other end of the link.
Propagate copy to link and opposite role player - the copied group includes a copy of the element at the
other end of the link.

The changes that you make will affect both the elements and the image that is copied.

Programming Copy and Paste Behavior


Many aspects of a DSL's behavior with regard to copy, paste, creation, and deletion of objects are governed by an
instance of ElementOperations that is coupled to the diagram. You can modify your DSL's behavior by deriving
your own class from ElementOperations and overriding the ElementOperations property of your diagram class.

TIP
For more information about customizing the model by using program code, see Navigating and Updating a Model in
Program Code.
To define your own ElementOperations
1. In a new file in your DSL project, create a class that is derived from DesignSurfaceElementOperations.
2. Add a partial class definition for your diagram class. The name of this class can be found in
Dsl\GeneratedCode\Diagrams.cs.
In the diagram class, override ElementOperations to return an instance of your ElementOperations
subclass. You should return the same instance at every call.
Add this code in a custom code file in the DslPackage project:
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement;

public partial class MyDslDiagram


{
public override DesignSurfaceElementOperations ElementOperations
{
get
{
if (this.elementOperations == null)
{
this.elementOperations = new MyElementOperations(this.Store as IServiceProvider, this);
}
return this.elementOperations;
}
}
private MyElementOperations elementOperations = null;
}

public class MyElementOperations : DesignSurfaceElementOperations


{
public MyElementOperations(IServiceProvider serviceProvider, MyDslDiagram diagram)
: base(serviceProvider, diagram)
{ }
// Overridden methods follow
}

Receiving items dragged from other models


ElementOperations can also be used to define copy, move, deletion and drag-and-drop behavior. As a
demonstration of the use of ElementOperations, the example given here defines custom drag-and-drop behavior.
However, for that purpose you might consider the alternative approach described in How to: Add a Drag-and-
Drop Handler, which is more extensible.
Define two methods in your ElementOperations class:
CanMerge(ModelElement targetElement, System.Windows.Forms.IDataObject data)which determines whether
the source element can be dragged onto the target shape, connector or diagram.
MergeElementGroupPrototype(ModelElement targetElement, ElementGroupPrototype sourcePrototype) which
combines the source element into the target.
CanMerge ()
CanMerge() is called to determine feedback that should be given to the user as the mouse moves across the
diagram. The parameters to the method are the element over which the mouse is hovering, and data about the
source from which the drag operation has been performed. The user can drag from anywhere on the screen.
Therefore, the source object can be of many different types and can be serialized in different formats. If the
source is a DSL or UML model, the data parameter is the serialization of an ElementGroupPrototype. Drag, copy
and toolbox operations use ElementGroupPrototypes to represent fragments of models.
An Element Group Prototype can contain any number of elements and links. Element types can be identified by
their GUIDs. The GUID is of the shape that was dragged, not the underlying model element. In following example,
CanMerge() returns true if a class shape from a UML diagram is dragged onto this diagram.
public override bool CanMerge(ModelElement targetShape, System.Windows.Forms.IDataObject data)
{
// Extract the element prototype from the data.
ElementGroupPrototype prototype = ElementOperations.GetElementGroupPrototype(this.ServiceProvider, data);
if (targetShape is MyTargetShape && prototype != null &&
prototype.RootProtoElements.Any(rootElement =>
rootElement.DomainClassId.ToString()
== "3866d10c-cc4e-438b-b46f-bb24380e1678")) // Guid of UML Class shapes
// or SourceClass.DomainClassId
return true;
return base.CanMerge(targetShape, data);
}

MergeElementGroupPrototype()
This method is called when the user drops an element onto a diagram, a shape, or a connector. It should merge
the dragged content into the target element. In this example, the code determines whether it recognizes the
combination of target and prototype types; if so, the method converts the dragged elements into a prototype of
the elements that should be added to the model. The base method is called to perform the merge, either of the
converted or unconverted elements.

public override void MergeElementGroupPrototype(ModelElement targetShape, ElementGroupPrototype


sourcePrototype)
{
ElementGroupPrototype prototypeToMerge = sourcePrototype;
MyTargetShape pel = targetShape as MyTargetShape;
if (pel != null)
{
prototypeToMerge = ConvertDraggedTypeToLocal(pel, sourcePrototype);
}
if (prototypeToMerge != null)
base.MergeElementGroupPrototype(targetShape, prototypeToMerge);
}

This example deals with UML class elements dragged from a UML class diagram. The DSL is not designed to
store UML classes directly, but instead, we create a DSL element for each dragged UML class. This would be
useful, for example, if the DSL is an instance diagram. The user could drag classes onto the diagram to create
instances of those classes.
private ElementGroupPrototype ConvertDraggedTypeToLocal (MyTargetShape snapshot, ElementGroupPrototype
prototype)
{
// Find the UML project:
EnvDTE.DTE dte = snapshot.Store.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
foreach (EnvDTE.Project project in dte.Solution.Projects)
{
IModelingProject modelingProject = project as IModelingProject;
if (modelingProject == null) continue; // not a modeling project
IModelStore store = modelingProject.Store;
if (store == null) continue;
// Look for the shape that was dragged:
foreach (IDiagram umlDiagram in store.Diagrams())
{
// Get modeling diagram that implements UML diagram:
Diagram diagram = umlDiagram.GetObject<Diagram>();
Guid elementId = prototype.SourceRootElementIds.FirstOrDefault();
ShapeElement shape = diagram.Partition.ElementDirectory.FindElement(elementId) as ShapeElement;
if (shape == null) continue;
IClass classElement = shape.ModelElement as IClass;
if (classElement == null) continue;

// Create a prototype of elements in my DSL, based on the UML element:


Instance instance = new Instance(snapshot.Store);
instance.Type = classElement.Name;
// Pack them into a prototype:
ElementGroup group = new ElementGroup(instance);
return group.CreatePrototype();
}
}
return null;
}

Standard Copy Behavior


The code in this section shows methods that can you can override to alter copying behavior. To help you see how
to achieve your own customizations, this section shows code that overrides the methods involved in copying, but
does not change the standard behavior.
When the user presses CTRL+C or uses the Copy menu command, the method ProcessOnMenuCopyCommand
is called. You can see how this is set up in DslPackage\Generated Code\CommandSet.cs. For more
information about how commands are set up, see How to: Add a Command to the Shortcut Menu.
You can override ProcessOnMenuCopyCommand by adding a partial class definition of MyDsl
ClipboardCommandSet in the DslPackage project.
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

partial class MyDslClipboardCommandSet


{
/// <summary>
/// Override ProcessOnMenuCopyCommand() to copy elements to the
/// clipboard in different formats, or to perform additional tasks
/// before or after copying - for example deselect the copied elements.
/// </summary>
protected override void ProcessOnMenuCopyCommand()
{
IList<ModelElement> selectedModelElements = this.SelectedElements;
if (selectedModelElements.Count == 0) return;

// System container for clipboard data.


// The IDataObject can contain data in several formats.
IDataObject dataObject = new DataObject();

Bitmap bitmap = null; // For export to other programs.


try
{
#region Create EGP for copying to a DSL.
this.CopyModelElementsIntoElementGroupPrototype
(dataObject, selectedModelElements);
#endregion

#region Create bitmap for copying to another application.


// Find all the shapes associated with this selection:
List<ShapeElement> shapes = new List<ShapeElement>(
this.ResolveExportedShapesForClipboardImages
(dataObject, selectedModelElements));

bitmap = this.CreateBitmapForClipboard(shapes);
if (bitmap != null)
{
dataObject.SetData(DataFormats.Bitmap, bitmap);
}
#endregion

// Add the data to the clipboard:


Clipboard.SetDataObject(dataObject, true, 5, 100);
}
finally
{
// Dispose bitmap after SetDataObject:
if (bitmap != null) bitmap.Dispose();
}
}
/// <summary>
/// Override this to customize the element group that is copied to the clipboard.
/// </summary>
protected override void CopyModelElementsIntoElementGroupPrototype(IDataObject dataObject,
IList<ModelElement> selectedModelElements)
{
return this.ElementOperations.Copy(dataObject, selectedModelElements);
}
}

Each diagram has a singleton instance of ElementOperations. You can supply your own derivative. This file, which
can be placed in the DSL project, would behave the same as the code that it overrides:

using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

namespace Company.MyDsl
{
partial class MyDslDiagram
{
/// <summary>
/// Singleton ElementOperations attached to this diagram.
/// </summary>
public override DesignSurfaceElementOperations ElementOperations
{
get
{
if (this.elementOperations == null)
{
this.elementOperations = new MyElementOperations(this.Store as IServiceProvider, this);
}
return this.elementOperations;
}
}
private MyElementOperations elementOperations = null;
}

// Our own version of ElementOperations so that we can override:


public class MyElementOperations : DesignSurfaceElementOperations
{
public MyElementOperations(IServiceProvider serviceProvider, ElementOps1Diagram diagram)
: base(serviceProvider, diagram)
{ }

/// <summary>
/// Copy elements to the clipboard data.
/// Provides a hook for adding custom data.
/// </summary>
public override void Copy(System.Windows.Forms.IDataObject data,
ICollection<ModelElement> elements,
ClosureType closureType,
System.Drawing.PointF sourcePosition)
{
if (CanAddElementGroupFormat(elements, closureType))
{
AddElementGroupFormat(data, elements, closureType);
}

// Override these to store additional data:


if (CanAddCustomFormat(elements, closureType))
{
AddCustomFormat(data, elements, closureType, sourcePosition);
}
}

protected override void AddElementGroupFormat(System.Windows.Forms.IDataObject data,


ICollection<ModelElement> elements, ClosureType closureType)
{
// Add the selected elements and those implied by the propagate copy rules:
ElementGroup elementGroup = this.CreateElementGroup(elements, closureType);

// Mark all the elements that are not embedded under other elements:
this.MarkRootElements(elementGroup, elements, closureType);

// Store in the clipboard data:


ElementGroupPrototype elementGroupPrototype = this.CreateElementGroupPrototype(elementGroup, elements,
closureType);
data.SetData(ElementGroupPrototype.DefaultDataFormatName, elementGroupPrototype);
}
/// <summary>
/// Override this to store additional elements in the element group:
/// </summary>
protected override ElementGroupPrototype CreateElementGroupPrototype(ElementGroup elementGroup,
ICollection<ModelElement> elements, ClosureType closureType)
{
ElementGroupPrototype prototype = new ElementGroupPrototype(this.Partition, elementGroup.RootElements,
elementGroup);
return prototype;
}

/// <summary>
/// Create an element group from the given starting elements, using the
/// copy propagation rules specified in the DSL Definition.
/// By default, this includes all the embedded descendants of the starting elements,
/// and also includes reference links where both ends are already included.
/// </summary>
/// <param name="startElements">model elements to copy</param>
/// <param name="closureType"></param>
/// <returns></returns>
protected override ElementGroup CreateElementGroup(ICollection<ModelElement> startElements, ClosureType
closureType)
{
// ElementClosureWalker finds all the connected elements,
// according to the propagate copy rules specified in the DSL Definition:
ElementClosureWalker walker = new ElementClosureWalker(this.Partition,
closureType, // Normally ClosureType.CopyClosure
startElements,
true, // Do not load other models.
null, // Optional list of domain roles not to traverse.
true); // Include relationship links where both ends are already included.

walker.Traverse(startElements);
IList<ModelElement> closureList = walker.ClosureList;
Dictionary<object, object> closureContext = walker.Context;

// create a group for this closure


ElementGroup group = new ElementGroup(this.Partition);
group.AddRange(closureList, false);

// create the element group prototype for the group


foreach (object key in closureContext.Keys)
{
group.SourceContext.ContextInfo[key] = closureContext[key];
}

return group;
}
}
}

See Also
Customizing Element Creation and Movement
How to: Add a Drag-and-Drop Handler
Customizing Deletion Behavior
Sample: VMSDK Circuit Diagrams sample

In this release of Visual Studio, the Text Template Transformation SDK and the Visual Studio Modeling SDK
are installed automatically when you install specific features of Visual Studio. For more details, see this blog
post.
Customizing Deletion Behavior
10/18/2017 10 min to read Edit Online

Deleting an element usually causes related elements to be deleted also. All relationships connected to it, and any
child elements are deleted. This behavior is named delete propagation. You can customize delete propagation, for
example to arrange that additional related elements are deleted. By writing program code, you can make delete
propagation depend on the state of the model. You can also cause other changes to occur in response to a
deletion.
This topic includes the following sections:
Default Deletion Behavior
Setting the Propagate Delete option of a role
Overriding the Delete Closure - Use this technique where deletion might lead to deletion of neighboring
elements.
Using OnDeleting and OnDeleted - Use these methods where the response could include other actions such
as updating a value either inside or outside the store.
Deletion Rules - Use rules to propagate updates of any kind within the store, where one change might lead
to others.
Deletion Events - Use store events to propagate updates outside the store, for example to other Visual
Studio documents.
UnMerge - use the UnMerge operation to undo the merge operation that attached a child element to its
parent.

Default Deletion Behavior


By default, the following rules govern delete propagation:
If an element is deleted, all embedded elements are also deleted. The embedded elements are those that are
the targets of embedding relationships for which this element is the source. For example, if there is an
embedding relationship from Album to Song, then when a particular Album is deleted, all its Songs will
also be deleted.
By contrast, deleting a song does not delete the album.
By default, deletion does not propagate along reference relationships. If there is a reference relationship
ArtistPlaysOnAlbum from Album to Artist, deleting an album does not delete any related artist, and
deleting an artist does not delete any album.
However, deletion does propagate along some built-in relationships. For example, when a model element is
deleted, its shape on the diagram is also deleted. The element and shape are related by the
PresentationViewsSubject reference relationship.

Every relationship that is connected to the element, either at the source or target role, is deleted. The role
property of the element at the opposite role no longer contains the deleted element.

Setting the Propagate Delete option of a role


You can cause deletion to propagate along a reference relationship, or from an embedded child to its parent.
To set delete propagation
1. On the DSL Definition diagram, select the role to which you want propagation to delete. The role is
represented by the line on the left or right of a domain relationship box.
For example, if you want to specify that whenever an Album is deleted, the related Artists are also deleted,
then select the role connected to the domain class Artist.
2. In the Properties window, set the Propagates Delete property.
3. Press F5 and verify that:
When an instance of this relationship is deleted, the element at the selected role will also be deleted.
When an element at the opposite role is deleted, instances of this relationship will be deleted, and the
related elements at this role will be deleted.
You can also see the Propagates Delete option in the DSL Details window. Select a domain class and, in
the DSL Details window, open the Delete Behavior page by clicking the button at the side of the window.
The Propagate option is shown for the opposite role of each relationship. The Delete Style column
indicates whether the Propagate option is at its default setting, but it does not have any separate effect.

Delete Propagation by using program code


The options in the DSL Definition file only let you choose whether deletion propagates to an immediate neighbor.
To implement a more complex scheme of delete propagation, you can write program code.

NOTE
To add program code to your DSL definition, create a separate code file in the Dsl project and write partial definitions to
augment the classes in the Generated Code folder. For more information, see Writing Code to Customise a Domain-Specific
Language.

Defining a Delete Closure


The deletion operation uses the class YourModelDeleteClosure to determine which elements to delete, given an
initial selection. It calls ShouldVisitRelationship() and ShouldVisitRolePlayer() repeatedly, walking the graph of
relationships. You can override these methods. ShouldVisitRolePlayer is provided with the identity of a link and the
element at one of the link's roles. It should return one of the following values:
VisitorFilterResult.Yes- The element should be deleted and the walker should proceed to try the element's
other links.
VisitorFilterResult.DoNotCare - The element should not be deleted unless another query replies that it
should be deleted.
VisitorFilterResult.Never - The element must not be deleted, even if another query answers Yes, and the
walker should not try the element's other links.
// When a musician is deleted, delete their albums with a low rating.
// Override methods in <YourDsl>DeleteClosure in DomainModel.cs
partial class MusicLibDeleteClosure
{
public override VisitorFilterResult ShouldVisitRolePlayer
(ElementWalker walker, ModelElement sourceElement, ElementLink elementLink,
DomainRoleInfo targetDomainRole, ModelElement targetRolePlayer)
{
ArtistAppearsInAlbum link = elementLink as ArtistAppearsInAlbum;
if (link != null
&& targetDomainRole.RolePlayer.Id == Album.DomainClassId)
{
// Count other unvisited links to the Album of this link.
if (ArtistAppearsInAlbum.GetLinksToArtists(link.Album)
.Where(linkAlbumArtist =>
linkAlbumArtist != link &&
!walker.Visited(linkAlbumArtist))
.Count() == 0)
{
// Should delete this role player:
return VisitorFilterResult.Yes;
}
else
// Don't delete unless another relationship deletes it:
return VisitorFilterResult.DoNotCare;
}
else
{
// Test for and respond to other relationships and roles here.

// Not the relationship or role we're interested in.


return base.ShouldVisitRolePlayer(walker, sourceElement,
elementLink, targetDomainRole, targetRolePlayer);
}
}
}

The closure technique ensures that the set of elements and links to be deleted is determined before deletion
begins. The walker also combines the results of your closure with those from other parts of the model.
However, the technique assumes that deletion affects only its neighbors in the graph of relationships: you cannot
use this method to delete an element in another part of the model. You cannot use it if you want to add elements
or make other changes in response to a deletion.

Using OnDeleting and OnDeleted


You can override OnDeleting() or OnDeleted() either in a domain class, or in a domain relationship.
1. OnDeleting is called when an element is about to be deleted, but before its relationships have been
disconnected. It is still navigable to and from other elements, and is still in store.ElementDirectory .
If several elements are deleted at the same time, OnDeleting is called for all of them before performing the
deletions.
IsDeleting is true.
2. OnDeleted is called when the element has been deleted. It remains in the CLR heap so that an Undo can be
performed if required, but it is unlinked from other elements and removed from store.ElementDirectory .
For relationships, the roles still reference the old role players. IsDeleted is true.
3. OnDeleting and OnDeleted are called when the user invokes Undo after a creating an element, and when an
earlier deletion is repeated in Redo. Use this.Store.InUndoRedoOrRollback to avoid updating store elements
in these cases. For more information, see How to: Use Transactions to Update the Model.
For example, the following code deletes an Album when its last child Song is deleted:

// Delete the parent Album when the last Song is deleted.


// Override methods in the embedding relationship between Album and Song:
partial class AlbumHasSongs
{
protected override void OnDeleted()
{
base.OnDeleted();
// Don't perform in-store actions in undo:
if (this.Store.InUndoRedoOrRollback) return;
// Relationship source and target still work:
// Don't bother if source is already on its way out:
if (!this.Album.IsDeleting && !this.Album.IsDeleted)
{
if (this.Album.Songs.Count == 0)
{
this.Album.Delete();
} } } }

It is often more useful to trigger from the deletion of the relationship than the role element, because this works
both when the element is deleted, and when the relationship itself is deleted. However, for a reference relationship,
you might want to propagate deletion when a related element is deleted, but not when the relationship itself is
deleted. This example deletes an Album when its last contributing Artist is deleted, but it does not respond if the
relationships are deleted:

using System.Linq; ...


// Assumes a many-many reference relationship
// between Artist and Album.
partial class Artist
{
protected override void OnDeleting()
{
base.OnDeleting();
if (this.Store.InUndoRedoOrRollback) return;
List<Album> toDelete = new List<Album>();
foreach (Album album in this.Albums)
{
if (album.Artists.Where(artist => !artist.IsDeleting)
.Count() == 0)
{
toDelete.Add(album);
}
}
foreach (Album album in toDelete)
{
album.Delete();
} } }

When you perform Delete on an element, OnDeleting and OnDeleted will be called. These methods are always
performed inline - that is, immediately before and after the actual deletion. If your code deletes two or more
elements, OnDeleting and OnDeleted will be called in alternation on all of them in turn.

Deletion Rules and Events


As an alternative to OnDelete handlers, you can define deletion rules and deletion events.
1. Deleting and Delete rules are triggered only in a transaction, and not in an Undo or Redo. You can set
them to be queued to execute at the end of the transaction in which the deletion is performed. Deleting
rules are always executed before any Deleted rules that are in the queue.
Use rules to propagate changes that affect only elements in the store, including relationships, diagram
elements and their properties. Typically, a Deleting rule is used to propagate deletion, and a Delete rule is
used to create replacement elements and relationships.
For more information, see Rules Propagate Changes Within the Model.
2. Deleted store event is invoked at the end of a transaction, and is called after an undo or redo. It can
therefore be used to propagate deletions to objects outside the store such as files, database entries or other
objects in Visual Studio.
For more information, see Event Handlers Propagate Changes Outside the Model.

WARNING
When an element has been deleted, you can access its domain property values, but you cannot navigate relationship
links. However, if you set a deleted event on a relationship, you can also access the two elements that were its role
players. Therefore, if you want to respond to the deletion of a model element but want to access an element to which
it was linked, set a delete event on the relationship instead of the model element's domain class.

Example Deletion Rules

[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]


internal class AlbumDeletingRule : DeletingRule
{
public override void ElementDeleting(ElementDeletingEventArgs e)
{
base.ElementDeleting(e);
// ...perform tasks to propagate imminent deletion
}
}
[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]
internal class AlbumDeletedRule : DeleteRule
{
public override void ElementDeleted(ElementDeletedEventArgs e)
{
base.ElementDeleted(e);
// ...perform tasks such as creating new elements
}
}

// The rule must be registered:


public partial class MusicLibDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(AlbumDeletingRule));
types.Add(typeof(AlbumDeletedRule));
// If you add more rules, list them here.
return types.ToArray();
}
}

Example Deleted Event


partial class NestedShapesSampleDocData
{
protected override void OnDocumentLoaded(EventArgs e)
{
base.OnDocumentLoaded(e);
DomainRelationshipInfo commentRelationship =
this.Store.DomainDataDirectory
.FindDomainRelationship(typeof(CommentsReferenceComponents));

this.Store.EventManagerDirectory.ElementDeleted.Add(commentRelationship,
new EventHandler<ElementDeletedEventArgs>(CommentLinkDeleted));
}

private void CommentLinkDeleted (object sender, ElementDeletedEventArgs e)


{
CommentsReferenceComponents link = e.ModelElement as CommentsReferenceComponents;
Comment comment = link.Comment;
Component component = link.Subject;
if (comment.IsDeleted)
{
// The link was deleted because the comment was deleted.
System.Windows.Forms.MessageBox.Show("Removed comment on " + component.Name);
}
else
{
// It was just the link that was deleted - the comment itself remains.
System.Windows.Forms.MessageBox.Show("Removed comment link to "
+ component.Name);
}
}
}

UnMerge
The operation that attaches a child element to its parent is called merge. It occurs when a new element or group of
elements is created from the toolbox, or moved from another part of the model, or copied from the clipboard. As
well as creating an embedding relationship between the parent and its new child, the merge operation can also set
up additional relationships, create auxiliary elements, and set property values in the elements. The merge operation
is encapsulated in an Element Merge Directive (EMD).
An EMD also encapsulates the complementary unmerge or MergeDisconnect operation. If you have a cluster of
elements that has been constructed by using a merge, it is recommended to use the associated unmerge to
remove an element from it, if you want to leave the remaining elements in a consistent state. The unmerge
operation will typically use the techniques described in the previous sections.
For more information, see Customizing Element Creation and Movement.

See Also
Customizing Copy Behavior
Customizing Element Creation and Movement
Writing Code to Customise a Domain-Specific Language
Customizing the Properties Window
10/18/2017 11 min to read Edit Online

You can customize the appearance and behavior of the properties window in your domain-specific language (DSL)
in Visual Studio. In your DSL Definition, you define domain properties on each domain class. By default, when you
select an instance of the class, either on a diagram or in Model Explorer, every domain property is listed in the
properties window. This lets you see and edit the values of domain properties, even if you have not mapped them
to shape fields on the diagram.

Names, Descriptions, and Categories


Name and Display Name. In your definition of a domain property, the Display Name of the property is the name
that appears at runtime in the properties window. By contrast, the Name is used when you write program code to
update the property. The Name must be a correct CLR alphanumeric name, but the Display Name can contain
spaces.
When you set the Name of a property in the DSL Definition, its Display Name is automatically set to a copy of the
Name. If you write a Pascal cased name such as "FuelGauge", the Display Name will automatically contain a space:
"Fuel Gauge". However, you can set the Display Name explicitly to another value.
Description. The Description of a domain property appears in two places:
In the bottom of the properties window when the user selects the property. You can use it to explain to the
user what the property represents.
In the generated program code. If you use the documentation facilities to extract API documentation, it will
appear as the description of this property in the API.
Category. A category is a heading in the Properties window.

Exposing Style Features


Some of the dynamic features of graphical elements can be represented or exposed as domain properties. A feature
that has been exposed in this manner can be updated by the user and can more easily be updated by program
code.
Right-click a shape class in DSL Definition, point to Add Exposed, and then choose a feature.
On shapes you can expose the FillColor, OutlineColor, TextColor, OutlineDashStyle, OutlineThickness and
FillGradientMode properties. On connectors you can expose the Color , TextColor, DashStyle, and Thickness
properties. On diagrams you can expose the FillColor and TextColor properties.

Forwarding: Displaying Properties of Related Elements


When the user of your DSL selects an element in a model, that element's properties are displayed in the properties
window. However, you can also display the properties of specified related elements. This is useful if you have
defined a group of elements that works together. For example, you might define a main element and an optional
plug-in element. If the main element is mapped to a shape and the other is not, it is useful to see all their properties
as if they were on one element.
This effect is named property forwarding, and it happens automatically in several cases. In other cases, you can
achieve property forwarding by defining a domain type descriptor.
Default Property Forwarding Cases
When the user selects a shape or connector, or an element in the Explorer, the following properties are displayed in
the Properties window:
The domain properties that are defined on the domain class of the model element, including those that are
defined in base classes. An exception is domain properties for which you have set Is Browsable to False .
The names of elements that are linked through relationships that have a multiplicity of 0..1. This provides a
convenient method of seeing optionally linked elements, even if you have not defined a connector mapping
for the relationship.
Domain properties of the embedding relationship that targets the element. Because embedding
relationships are usually not displayed explicitly, this lets the user see their properties.
Domain properties that are defined on the selected shape or connector.
Adding Property Forwarding
To forward a property, you define a domain type descriptor. If you have a domain relationship between two
domain classes, you can use a domain type descriptor to set a domain property in the first class to the value of a
domain property in the second domain class. For example, if you have a relationship between a Book domain class
and an Author domain class, you can use a domain type descriptor to make the Name property of a Book's
Author appear in the Properties window when the user selects the Book.

NOTE
Property forwarding affects only the Properties window when the user is editing a model. It does not define a domain
property on the receiving class. If you want to access the forwarded domain property in other parts of the DSL Definition or
in program code, you must access the forwarding element.

The following procedure assumes that you have created a DSL. The first few steps summarize the prerequisites.
To fo r w a r d a p r o p e r t y fr o m a n o t h e r e l e m e n t

1. Create a Domain-Specific Language Tools solution that contains at least two classes, which in this example
are called Book and Author. There should be a relationship of either kind between Book and Author.
The multiplicity of the source role (the role at the Book side) should be 0..1 or 1..1, so that each Book has
one Author.
2. In DSL Explorer, right-click the Book domain class, and then click Add New DomainTypeDescriptor.
A node named Paths of Custom Property Descriptors appears under the Custom Type Descriptor node.
3. Right-click the Custom Type Descriptor node, and then click Add New PropertyPath.
A new property path appears under the Paths Of Custom Property Descriptors node.
4. Select the new property path, and in the Properties window, set Path to Property to the path of the
appropriate model element.
You can edit the path in a tree view by clicking the down arrow to the right of this property. For more
information about domain paths, see Domain Path Syntax. When you have edited it, the path should
resemble BookReferencesAuthor.Author/!Author.
5. Set Property to the Name domain property of Author.
6. Set Display Name to Author Name.
7. Transform All Templates, build and run the DSL.
8. In a model diagram, create a book, an author, and link them using the reference relationship. Select the book
element, and in the Properties window you should see Author Name in addition to the properties of the
book. Change the name of the linked author, or link the book to a different author, and observe that the
Author Name of the book changes.

Custom Property Editors


The property window provides an appropriate default editing experience for the type of each domain property. For
example, for an enumerated type, the user sees a drop-down list, and for a numeric property, the user can enter
digits. This is only true for the built-in types. If you specify an external type, the user will be able to see the
property's values, but not edit it.
However, you can specify the following editors and types:
1. Another editor that is used with a standard type. For example, you could specify a file path editor for a string
property.
2. An external type for the domain property, and an editor for it.
3. A .NET editor such as the file path editor, or you can create your own custom property editor.
A conversion between an external type and an type such as String, which has a default editor.
In a DSL, an external type is any type that is not one of the simple types (such as Boolean or Int32) or String.
To define a domain property that has an external type
1. In Solution Explorer, add a reference to the assembly (DLL) that contains the external type, in the Dsl
project.
The assembly can be a .NET assembly, or an assembly supplied by you.
2. Add the type to the Domain Types list, unless you have already done so.
a. Open DslDefinition.dsl, and in DSL Explorer, right-click the root node, and then click Add New
External Type.
A new entry appears under the Domain Types node.

WARNING
The menu item is on the DSL root node, not the Domain Types node.

b. Set the name and the namespace of the new type in the Properties window.
3. Add a domain property to a domain class in the usual manner.
In the Properties window, select the external type from the drop-down list in the Type field.
At this stage, users can view the values of the property, but they cannot edit it. The displayed values are
obtained from the ToString() function. You could write program code that sets the value of the property,
for example in a command or rule.
Setting a Property Editor
Add a CLR attribute to the domain property, in the following form:

[System.ComponentModel.Editor (
typeof(AnEditor),
typeof(System.Drawing.Design.UITypeEditor))]
You can set the attribute on a property by using the Custom Attribute entry in the Properties window.
The type of AnEditor must be derived from the type specified in the second parameter. The second parameter
should be either UITypeEditor or ComponentEditor. For more information, see EditorAttribute.
You can specify either your own editor, or an editor supplied in the .NET Framework, such as FileNameEditor or
ImageEditor. For example, use the following procedure to have a property in which the user can enter a file name.
To d e fi n e a fi l e n a m e d o m a i n p r o p e r t y

1. Add a domain property to a domain class in your DSL Definition.


2. Select the new property. In the Custom Attribute field in the Properties window, enter the following
attribute. To enter this attribute, click the ellipsis [...] and then enter the attribute name and the parameters
separately:

[System.ComponentModel.Editor (
typeof(System.Windows.Forms.Design.FileNameEditor)
, typeof(System.Drawing.Design.UITypeEditor))]

3. Leave the Type of the domain property at its default setting of String.
4. To test the editor, verify that users can open the file name editor to edit your domain property.
a. Press CTRL+F5 or F5. In the debugging solution, open a test file. Create an element of the domain
class and select it.
b. In the Properties window, select the domain property. The value field shows an ellipsis [...].
c. Click the ellipsis. A file dialog box appears. Select a file and close the dialog box. The file path is now
the value of the domain property.
Defining your own property editor
You can define your own editor. You would do this to allow the user either to edit a type that you have defined, or
to edit a standard type in a special way. For example, you could allow the user to input a string that represents a
formula.
You define an editor by writing a class that is derived from UITypeEditor. Your class must override:
EditValue, to interact with the user and update the property value.
GetEditStyle, to specify whether your editor will open a dialog or provide a drop-down menu.
You can also provide a graphical representation of the property's value that will be displayed in the property
grid. To do this, override GetPaintValueSupported , and PaintValue . For more information, see UITypeEditor.

NOTE
Add the code in a separate code file in the Dsl project.

For example:
internal class TextFileNameEditor : System.Windows.Forms.Design.FileNameEditor
{
protected override void InitializeDialog(System.Windows.Forms.OpenFileDialog openFileDialog)
{
base.InitializeDialog(openFileDialog);
openFileDialog.Filter = "Text files(*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog.Title = "Select a text file";
}
}

To use this editor, set the Custom Attribute of a domain property to:

[System.ComponentModel.Editor (
typeof(MyNamespace.TextFileNameEditor)
, typeof(System.Drawing.Design.UITypeEditor))]

For more information, see UITypeEditor.

Providing a drop-down list of values


You can provide a list of values for a user to choose from.

NOTE
This technique provides a list of values that can change at runtime. If you want to provide a list that does not change,
consider instead using an enumerated type as the type of your domain property.

To define a list of standard values, you add to your domain property a CLR attribute that has the following form:

[System.ComponentModel.TypeConverter
(typeof(MyTypeConverter))]

Define a class that derives from TypeConverter. Add the code in a separate file in the Dsl project. For example:

/// <summary>
/// Type converter that provides a list of values
/// to be displayed in the property grid.
/// </summary>
/// <remarks>This type converter returns a list
/// of the names of all "ExampleElements" in the
/// current store.</remarks>
public class MyTypeConverter : System.ComponentModel.TypeConverter
{
/// <summary>
/// Return true to indicate that we return a list of values to choose from
/// </summary>
/// <param name="context"></param>
public override bool GetStandardValuesSupported
(System.ComponentModel.ITypeDescriptorContext context)
{
return true;
}

/// <summary>
/// Returns true to indicate that the user has
/// to select a value from the list
/// </summary>
/// <param name="context"></param>
/// <returns>If we returned false, the user would
/// be able to either select a value from
/// the list or type in a value that is not in the list.</returns>
public override bool GetStandardValuesExclusive
(System.ComponentModel.ITypeDescriptorContext context)
{
return true;
}

/// <summary>
/// Return a list of the values to display in the grid
/// </summary>
/// <param name="context"></param>
/// <returns>A list of values the user can choose from</returns>
public override StandardValuesCollection GetStandardValues
(System.ComponentModel.ITypeDescriptorContext context)
{
// Try to get a store from the current context
// "context.Instance" returns the element(s) that
// are currently selected i.e. whose values are being
// shown in the property grid.
// Note that the user could have selected multiple objects,
// in which case context.Instance will be an array.
Store store = GetStore(context.Instance);

List<string> values = new List<string>();

if (store != null)
{
values.AddRange(store.ElementDirectory
.FindElements<ExampleElement>()
.Select<ExampleElement, string>(e =>
{
return e.Name;
}));
}
return new StandardValuesCollection(values);
}

/// <summary>
/// Attempts to get to a store from the currently selected object(s)
/// in the property grid.
/// </summary>
private Store GetStore(object gridSelection)
{
// We assume that "instance" will either be a single model element, or
// an array of model elements (if multiple items are selected).

ModelElement currentElement = null;

object[] objects = gridSelection as object[];


if (objects != null && objects.Length > 0)
{
currentElement = objects[0] as ModelElement;
}
else
{
currentElement = gridSelection as ModelElement;
}

return (currentElement == null) ? null : currentElement.Store;


}

See Also
Navigating and Updating a Model in Program Code
Customizing the Model Explorer
10/18/2017 3 min to read Edit Online

You can change the appearance and behavior of the explorer for your domain-specific language designer as
follows:
Change the window title.
Change the tab icon.
Change the icons for nodes.
Hide nodes.

Changing the Window Title


To change the window title of the generated explorer, select Explorer Behavior in the DSL Explorer, and then in
the Properties window, set the Title property to the title you want.

Changing the Tab Icon


To change the tab icon for the explorer, use a 16x16-pixel icon in a .bmp file. Put the icon file in the
\DslPackage\Resources\ folder, and then change the file name to ModelExplorerToolWindowBitmaps.bmp. For
example, you could change the Visual Studio setup.ico icon file to .bmp format and rename it to
DSLLanguageName\DslPackage\Resources\ModelExplorerToolWindowBitmaps.bmp. The generated
designer will display this icon on the tab of your explorer when it is docked together with Solution Explorer.

Setting Custom Icons on Explorer Nodes


You can customize nodes in your explorer by using explorer node settings. The following procedure shows how to
add an icon to a node.
To add an icon to an explorer node
1. Create a Domain-Specific Language Tools solution by using the Task Flow solution template.
2. Put a .bmp file that contains a 16x16-pixel icon in the Dsl\Resources folder in the solution.
3. In the DSL Explorer, right-click Explorer Behavior and then click Add New Explorer Node Settings.
An ExplorerNodeSettings node appears under the Custom Node Settings node.
4. Select ExplorerNodeSettings, and then in the Properties window, set Class to Actor.
5. Set Icon To Display to the path of the icon file.
6. Transform all templates, and then build and run the solution.
7. In the generated designer, open the Sample diagram.
The Explorer should show three Actor nodes that have your icon.
NOTE
If you have set a node icon for any element that is displayed in the generated explorer, all explorer nodes will display the icon.
If no icon has been set, the nodes will display the default icon.

Changing the Name Displayed on an Explorer Node


You can change how the names of model elements are displayed in your explorer. The following procedure shows
how to display the name of the Task that is referenced by a Comment in the comment node.
To display a property
1. Open the solution that you created in the earlier procedure.
2. Make sure that the Comment references only a single domain class by setting the multiplicity of the role
with property name Subjects to 0..1. The property name should become Subject, and the relationship name
should become CommentReferencesSubject.
3. In the DSL Explorer, right-click Explorer Behavior and then click Add New Explorer Node Settings.
An ExplorerNodeSettings node appears under the Custom Node Settings node.
4. Select ExplorerNodeSettings, and then in the Properties window, set Class to Comment.
5. Right-click the Comment node, and then click Add New Property Path.
A new node appears that is named Property Displayed.
6. Select Property Displayed, and then in the Properties window, click the value field of Path To Property.
Select Comment, then CommentReferencesSubject, then FlowElement. The resulting path should
resemble CommentReferencesSubject.Subject/!Subject.
7. In the value field of Property, select Name.
8. Transform all templates, and then build and run your solution.
9. In the generated designer, open the Sample diagram.
10. Draw a Comment Connector between the comment element and the Task1 element on the diagram.
The Explorer node should display the comment as Task1.

Hiding Nodes
You can hide a node in your explorer by adding its path to the Hidden Nodes node of the DSL Explorer. The
following procedure shows how to hide Comment nodes.
To hide an explorer node
1. Open the solution that you created in the earlier procedure.
2. In the DSL Explorer, right-click Explorer Behavior and then click Add New Domain Path.
A Domain Path node appears under Hidden Nodes.
3. Select Domain Path, and then in the Properties window, click the value field of Path Definition. Select
FlowGraph, then FlowGraphHasComments. The resulting path should resemble
FlowGraphHasComments.Comments
4. Transform all templates, and then build and run your solution.
5. In the generated designer, open the Sample diagram.
The explorer should show only an Actors node, and should not show the Comments node.

See Also
Domain-Specific Language Tools Glossary
Domain Path Syntax
10/18/2017 1 min to read Edit Online

DSL Definitions use an XPath-like syntax to locate specific elements in a model.


Ordinarily you do not have to work with this syntax directly. Where it appears in DSL Details or Properties window,
you can click the downward arrow and use the path editor. However, the path appears in this form in the field after
you have used the editor.
A domain path takes the following form:
RelationshipName.PropertyName/!Role

The syntax traverses the tree of the model. For example, the domain relationship CommentReferencesSubjects in
the illustration above has a Subjects role. The path segment /!Subjectt specifies that the path finishes on elements
accessed through the Subjects role.
Each segment starts with the name of a domain relationship. If the traversal is from an element to a relationship,
the path segment appears as Relationship.PropertyName. If the hop is from a link to an element, the path segment
appears as Relationship/!RoleName.
Slashes separate the syntax of a path. Each path segment is either a hop from an element to a link (an instance of a
relationship) or from a link to an element. Path segments frequently appear in pairs. One path segment represents
a hop from an element to a link, and the next segment represents a hop from the link to the element at the other
end. (Any link can also be the source or target of a relationship itself).
The name that you use for the element-to-link hop is the value of the role's Property Name . The name that you use
for the link-to-element hop is the target role name.

See Also
Understanding Models, Classes and Relationships
Properties of Model Elements
10/18/2017 1 min to read Edit Online

This section lists the properties that you see in the Properties window when you select an element in the DSL
Definition diagram or in the DSL Explorer.
In some cases, additional properties can be found in the DSL Details window.

Related Sections
Customizing and Extending a Domain-Specific Language
Overriding and Extending the Generated Classes
How to Define a Domain-Specific Language
Properties of a DSL Definition
10/18/2017 1 min to read Edit Online

DslDefinition properties define domain-specific language definition properties such as version numbering. The
DslDefinition properties appear in the Properties window when you click an open area of the diagram in the
Domain-Specific Language Designer.
For more information, see How to Define a Domain-Specific Language. For more information about how to use
these properties, see Customizing and Extending a Domain-Specific Language.
DslDefinition has the properties in the following table:

PROPERTY DESCRIPTION DEFAULT

Access Modifier Determines if the access modifier for the public


domain class is public or internal.

Custom Attributes Custom defined attributes for the <none>


domain class.

Note Use the browse button to add an


attribute.

Company Name The name of the current company name Current company name
in the system registry.

Name The name of this domain class. Current name

Namespace The namespace affiliated with this Current namespace


domain class.

Package Guid The guid for the Visual Studio package <none>
generated for this DSL.

Package Namespace The namespace for the Visual Studio <none>


package generated for this DSL.

Product Name The name of the product that will be <none>


registered for the Visual Studio package
generated for this DSL.

Notes Notes associated with this domain class. <none>

Description Description for this domain class. <none>

Display Name The name that will be displayed in the <none>


generated designer for this domain
class.

Help Keyword The help keyword associated with this <none>


domain class.
PROPERTY DESCRIPTION DEFAULT

Build The incremental build number for this 0


domain-specific language definition.

Major Version The incremental major build number for 1


this domain-specific language definition.

Minor Version The incremental minor build number for 0


this domain-specific language definition.

Revision The incremental revision build number 0


for this domain-specific language
definition.

See Also
Domain-Specific Language Tools Glossary
Properties of Domain Classes
10/18/2017 1 min to read Edit Online

Domain classes have the properties in the following table. For information about domain classes, see
Understanding Models, Classes and Relationships. For more information about how to use these properties, see
Customizing and Extending a Domain-Specific Language.

PROPERTY DESCRIPTION DEFAULT

Access Modifier The level of access of the domain class ( public


public or internal ).

Custom Attributes Used to add attributes to the source <none>


code class that is generated from this
domain class.

Generates Double Derived If True , both a base class and a partial False
class (to support customization through
overrides) will be generated. For more
information, see Overriding and
Extending the Generated Classes.

Has Custom Constructor If True , a custom constructor will be False


provided in the source code. For more
information, see Overriding and
Extending the Generated Classes.

Inheritance Modifier Describes the kind of inheritance of the none


source code class that is generated from
the domain class ( none , abstract or
sealed ).

Base Class If this domain class is derived, the name <none>


of the base class.

Name The name of this domain class. Current name

Namespace The namespace of this domain class. Current namespace

Notes Informal notes that are associated with <none>


this domain class.

Description The description that is used to <none>


document the UI of the generated
designer.

Display Name The name that will be displayed in the <none>


generated designer for this domain
class.

Help Keyword The optional keyword that is used to <none>


index F1 help for this domain class.
See Also
Domain-Specific Language Tools Glossary
Properties of Domain Properties
10/18/2017 3 min to read Edit Online

A domain property is a feature of a model element that can hold a value. For example, the Person domain class
could have properties Name and BirthDate . In the DSL Definition, domain properties are listed in the domain class
box on the diagram and under the domain class in DSL Explorer. For more information, see How to Define a
Domain-Specific Language.

NOTE
The word "property" has two uses. A domain property is a feature that you define on a domain class. By contrast, many
elements of a DSL have properties, which are listed in the Properties window in the DSL Definition. For example, every
domain property has a set of properties, which are described in this topic.

At run time, when a user creates instances of the domain class, the values of the domain properties can be seen in
the Properties window, and can be displayed on the shapes.
Most domain properties are implemented as ordinary CLR properties. However, from a programming point of view,
domain properties have richer functionality than ordinary program properties:
You can define rules and events that monitor the state of a property. For more information, see Responding
to and Propagating Changes.
Transactions help prevent inconsistent states. For more information, see Navigating and Updating a Model in
Program Code.
When you select a Domain Property in a diagram or in DSL Explorer, you can see the following items in the
Properties window. For more information about how to use these items, see Customizing and Extending a
Domain-Specific Language.

PROPERTY DESCRIPTION DEFAULT VALUE

Description The description that is used to <none>


document the user interface (UI) of the
generated designer.

Display Name The name that will be displayed in the <none>


generated designer for this domain
property. It can contain spaces and
punctuation, for example "Song Title".
PROPERTY DESCRIPTION DEFAULT VALUE

Element Name Provider This is applicable only if you have set <none>
Is Element Name to true . You can
write code that provides a name for a
new element of a domain class,
overriding the default behavior.

In a code file in the DSL project, create a


class that is derived from
ElementNameProvider.

Then in DSL Explorer, right-click the


root of the DSL, and click Add External
Type. Enter the name of your class.

Select this domain property again, and


select the name of the class in the drop-
down list.

Getter Access Modifier The level of access of the domain class ( public
public or internal ). This controls
the scope in which program code can
access the property.

Help Keyword The optional keyword that is used to <none>


index F1 help for this domain property.

Is Browsable If True , the domain property is True


displayed to the user in the properties
window when models of this DSL are
open.

If False , the domain property is


hidden in the UI.

If you want to make the domain


property visible but read-only, set Is UI
Read Only.

Is Element Name If True , this domain property will be False


displayed as the name of its model
element in DSL Explorer.

New model elements will receive a


unique default value for this property. If
you want to control how these values
are generated, set Element Name
Provider.
PROPERTY DESCRIPTION DEFAULT VALUE

Is UI Read Only If True , the value of the domain False


property cannot be changed by using
the UI. It can still be set by programs,
and will be visible in the Properties
window.

If you want to hide the domain


property from the user, set Is
Browsable. If you want to control
access by programs, set Setter Access
Modifier.

Kind The kind of domain property ( Normal , Normal


Calculated , or CustomStorage ). For
more information, see Calculated and
Custom Storage Properties.

Name The name of this domain property. It <none>


must be a valid identifier, for example
SongTitle.

Notes Informal notes that are associated with <none>


this domain property.

Setter Access Modifier The access modifier for the setter. This public
controls the scope in which program
code can set the property.

Type The type of property. To add to the list String


of available types, right-click the root of
the DSL in DSL explorer, and click Add
External Type.

See Also
Domain-Specific Language Tools Glossary
Properties of Domain Relationships
10/18/2017 1 min to read Edit Online

The properties in the following table are associated with a domain relationship. For information about domain
relationships, see Understanding Models, Classes and Relationships. For more information about how to use these
properties, see Customizing and Extending a Domain-Specific Language.

PROPERTY DESCRIPTION DEFAULT

Access Modifier The level of access of the domain public


relationship ( public or internal ).

Custom Attributes Used to add attributes to the source <none>


code class that is generated from the
domain relationship.

Generates Double Derived If True , both a base class and a partial False
class (to support customization through
overrides) is generated. For more
information, see Overriding and
Extending the Generated Classes.

Has Custom Constructor If True , indicates that a custom False


constructor is provided in the source
code. For more information, see
Overriding and Extending the
Generated Classes.

Inheritance Modifier Describes the kind of inheritance of the <none>


source code class that is generated
from the domain relationship ( none ,
abstract or sealed ).

Allows Duplicates If True , duplicate links of the domain False


relationship may be created between
the same two elements.

Base Relationships If the domain relationship is derived, <none>


the base relationship of the domain
relationship.

Is Embedding If True , the domain relationship is an <both>


embedding relationship. If False , the
relationship is a reference relationship.

Name The name of the domain relationship. Current name

Namespace The namespace that is affiliated with the Current namespace


domain relationship.

Notes Informal notes that are associated with <none>


the domain relationship.
PROPERTY DESCRIPTION DEFAULT

Description The description that is used to <none>


document code and is used in the UI of
the generated designer.

Display Name The name that is displayed in the <none>


generated designer for the domain
relationship.

Help Keyword The optional keyword that is used to <none>


index F1 help for the domain
relationship.

See Also
Domain-Specific Language Tools Glossary
Properties of Domain Roles
10/18/2017 3 min to read Edit Online

The properties in the following table are associated with a domain role. For information about domain roles, see
Understanding Models, Classes and Relationships. For more information about how to use these properties, see
Customizing and Extending a Domain-Specific Language.

PROPERTY DESCRIPTION DEFAULT

Collection Type If this role has multiplicity of 0..* or 1..*, (none) - LinkedElementCollection<T>
this property customizes the generic is used
type that is used to store the collection
of links.

Custom Attributes Attributes that you specify here will be <none>


added as attributes to the generated
code class.

Is Property Browsable If True , and if the multiplicity of the True


relationship is 0..1 or 1..1, the role
property can be browsed by the user in
the Properties window. The property
displays the name of the element at the
other end of the relationship link.

Is Property Generator If True , a role property is generated True


for this role, which you can use to
traverse the relationship in program
code. If you set this false, you can
traverse the relationship in a less
efficient manner by using static
methods of the domain relationship.

Property Getter Access Modifier The access modifier for the getter for public
the generated property ( public ,
internal , private , protected , or
protected internal ).

Property Setter Access Modifier The access modifier for the setter for public
the generated property ( public ,
internal , private , protected , or
protected internal ).

Multiplicity The number of model elements which Depends on the relationship type and
can play the opposite role ( 0..1 , whether this is the source or target role
1..1 , 0..* , or 1..* ). If the in the relationship.
multiplicity is 0..* or 1..* , then the
generated property represents a
collection; otherwise, the generated
property represents a single