T4 and Templates - TOC
T4 and Templates - TOC
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
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)
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
To see which versions of Visual Studio support each feature, see Version support for architecture and modeling
tools
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:
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:
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:
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
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.
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.
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
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.
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:
DIAGRAMS DESCRIBES
DIAGRAM DESCRIBES
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
DIAGRAM DESCRIBES
DIAGRAM DESCRIPTION
See:
See:
DIAGRAM DESCRIPTION
See:
External Resources
CATEGORY LINKS
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
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.
Understand class structures: How to: Add Class Diagrams to Projects (Class Designer)
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
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.
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.
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.
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.
Show Base Types For a class, add the base class and the implemented
interfaces.
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 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.
Show Methods This Calls Add methods that this method calls.
Show Fields This References Add fields that this method references.
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.
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.
The program database (.pdb) file might Turn on the /DEBUG option in the
not be built. linker.
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.
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.
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 .
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.
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.
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 map will update automatically while you continue debugging. See Update the map with the next call
stack.
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:
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:
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.
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.
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.
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.
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.
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.
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 -
Undo an action in the map. Press CTRL + Z or use the Visual Studio Undo command.
Scan the map. Drag the map in any direction using the mouse.
- or -
- or -
- or -
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 -
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.
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:
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.
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.
See more information about a node or a link. Move the mouse pointer on top of the node or link until a
tooltip appears.
- 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-
-or-
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.
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.
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
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.
Show cross-group links at all times. Show All Cross-Group Links. This hides aggregated links
between groups.
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.
Change the layout inside a group. Select the group, open the shortcut menu, choose Layout,
and select the layout style you want.
- or -
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.
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 -
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.
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.
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.
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.
Compiled .NET assemblies (.dll or .exe) or binaries. Drag the assemblies or binaries from outside Visual Studio to
a map.
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
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 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.
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:
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:
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.
TO CHOOSE
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.
<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.
Background="ColorNameOrHexadecimalValue"
Border color
Stroke="StrokeValue"
For example:
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
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"
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
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
<Condition Expression="MyCategory"/>
or -
or -
<Condition Expression="HasCategory('MyCategory')"/>
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 .
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>
<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>
<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>
<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>
<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>
<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 .
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>
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:
<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:
<Links></Links>
This element contains the list of <Link> elements, which define links between nodes. For more information,
see the <Link/> element.
Example:
<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.
<Categories></Categories>
This element contains the list of <Category/> elements. For more information, see the <Category/>
element.
Example:
<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:
<Properties></Properties>
This element contains the list of <Property/> elements. For more information, see the <Property/>
element.
Example:
<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.
<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
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.
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.
Create a layer for a single artifact 1. Drag the item onto the dependency diagram from
these sources:
Solution Explorer
Create a single layer for all selected artifacts Drag all the artifacts to the dependency diagram at the same
time.
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.
Create a new unlinked layer In the Toolbox, expand the Dependency Diagram section,
and then drag a Layer to the dependency diagram.
- or -
- 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.
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.
Create new dependencies Use the Dependency and Bidirectional Dependency tools.
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.
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
Related Tasks
TOPIC TASK
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
External Resources
CATEGORY LINKS
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.
The following table describes the elements that you can use on a dependency diagram.
- 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.
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.
Supports Validation If True, then the layer validation process can verify that
the project conforms to dependencies to or from this
element.
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.
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.
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.
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
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.
Delete a dependency that should not exist Click the dependency, and then press DELETE.
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.
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.
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.
Related Topics
TITLE DESCRIPTION
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.
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.
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.
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.
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.
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.
External Resources
CATEGORY LINKS
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.
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.
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:
How to develop code that adheres to business rules Model your app's architecture
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.
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.
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
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. 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.
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.
Make sure your software meets the users' requirements: - Develop tests from a model
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
External Resources
CATEGORY LINKS
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.
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.
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
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.
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.
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:
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:
Suppress selected errors during validation Right-click the one or multiple selected errors, point to
Manage Validation Errors, and then click Suppress Errors.
Stop suppressing selected errors Right-click the selected suppressed error or errors, point to
Manage Validation Errors, and then click Stop
Suppressing Errors.
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.
<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
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.
SYNTAX DESCRIPTION
MySolution.MyProject.MyClass.MyMethod(Method)
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.
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.
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.
[Export(typeof(ICommandExtension))]
...
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;
[Import]
public ILinkedUndoContext LinkedUndoContext { get; set; }
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.
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.
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;
...
} }
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");
// 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.
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
<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
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)
{ }
/// <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:
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.
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.
NOTE
%LocalAppData% is typically DriveName:UsersUserNameAppDataLocal.
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.
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.
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
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:
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.
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.
This solution defines a domain specific language. For more information, see Overview of the Domain-
Specific Language Tools User Interface.
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:
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.
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
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.
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.
<#
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.
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 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.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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
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()
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.
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.
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
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
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).
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.
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.
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.
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.
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:
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;
...
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.
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);
/// <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);
}
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.
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
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:
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:
3. In the code behind the user control, insert methods to listen for elements added and removed:
public partial class UserControl1 : UserControl { ...
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
Editor
Toobox Tabs
MyDsl //a tab
Tools
ExampleElement // an element tool
ExampleRelationship // a connection tool
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.
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
transistor.Base.Name = "base";
transistor.Collector.Name = "collector";
transistor.Emitter.Name = "emitter";
return elementGroup.CreatePrototype();
}
else
{
return base.CreateElementToolPrototype(store, domainClassId);
} } }
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.
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
/// <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 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.
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.
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.
// Custom actions:
ExampleElement mergingElement = sourceElement as ExampleElement;
if (mergingElement != null)
{
mergingElement.Name = DateTime.Now.ToLongTimeString();
}
}
}
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.
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.
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);
}
if (!docView.IsContextMenuShowing)
{
// User hit CTRL+V - just use base method.
// Utility class:
DesignSurfaceElementOperations op = diagram.ElementOperations;
The changes that you make will affect both the elements and the image that is copied.
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;
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.
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;
bitmap = this.CreateBitmapForClipboard(shapes);
if (bitmap != null)
{
dataObject.SetData(DataFormats.Bitmap, bitmap);
}
#endregion
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;
}
/// <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);
}
// Mark all the elements that are not embedded under other elements:
this.MarkRootElements(elementGroup, elements, closureType);
/// <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;
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.
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.
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.
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.
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:
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.
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.
this.Store.EventManagerDirectory.ElementDeleted.Add(commentRelationship,
new EventHandler<ElementDeletedEventArgs>(CommentLinkDeleted));
}
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.
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.
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
[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))]
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);
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).
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.
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
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:
Company Name The name of the current company name Current company name
in the system registry.
Package Guid The guid for the Visual Studio package <none>
generated for this DSL.
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.
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.
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.
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.
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.
Setter Access Modifier The access modifier for the setter. This public
controls the scope in which program
code can set the property.
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.
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.
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.
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.
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