Create Custom Diagram Items
- 7 minutes to read
Alongside a wide range of default diagram items (shapes, containers, connectors, and images), the DiagramControl
offers multiple techniques to create custom or pre-configured items:
- Pre-configure a Default Item and Register It in a New Stencil
- Combine Multiple Shapes into One
- Create Shapes Based on SVG Images
- Use Templates to Create Custom Shapes and Containers
- Extend a Default Diagram Item
Pre-configure a Default Item and Register It in a New Stencil
The code example below does the following:
- Creates an image item (DiagramImage). Specifies item dimensions and loads a predefined image.
- Wraps the pre-configured item into a tool (FactoryItemTool).
- Extends the Shapes Panel with a new group (DiagramStencil). Adds the new tool into the new stencil.
DiagramStencil myStencil = new DiagramStencil("myStencil", "Custom Items");
myStencil.RegisterTool(new FactoryItemTool(
"customItem",
() => "Custom Item",
diagram => new DiagramImage() { Image = "img.png" },
new Size(200, 30)
));
DiagramToolboxRegistrator.RegisterStencil(myStencil);
diagramControl1.SelectedStencils = new StencilCollection() { "myStencil" };
FactoryItemTool allows you to define a tool that creates diagram items on the canvas. You can display this tool in a DiagramStencil (Shapes Panel) or assign it to the DiagramControl.ActiveTool property. Underlying items can be the following objects or their descendants: DiagramShape, DiagramContainer, DiagramConnector, or DiagramImage.
Use FactoryItemTool in the following cases:
- To create an additional tool that adds and pre-configures a default diagram item.
- To create an additional tool that adds a diagram item descendant.
Note that you do not have to create and register new tools. Sometimes you may want to leave stencils and their item collections unchanged. You can still execute custom actions or modify settings when a user adds default items to the canvas. For this purpose, handle DiagramControl.ItemCreating and DiagramControl.ItemInitializing events.
Combine Multiple Shapes into One
You can use DiagramContainers with multiple inner shapes to create custom shapes. Use this technique if geometry of shapes may combine predefined shapes.
Create a container and add static non-selectable shapes:
public DiagramContainer CreateContainerShape1() { var container = new DiagramContainer(); container.StrokeThickness = 0; container.Background = Brushes.Transparent; var innerShape1 = new DiagramShape() { CanSelect = false, CanChangeParent = false, CanEdit = false, CanCopyWithoutParent = false, CanDeleteWithoutParent = false, CanMove = false, Shape = BasicShapes.Trapezoid, Anchors = Sides.Top | Sides.Left | Sides.Right, Height = 50, Width = 200, Content = "Custom text" }; var innerShape2 = new DiagramShape() { CanSelect = false, CanChangeParent = false, CanEdit = false, CanCopyWithoutParent = false, CanDeleteWithoutParent = false, CanMove = false, Shape = BasicShapes.Rectangle, Anchors = Sides.All, Height = 150, Width = 200, Position = new Point(0, 50), }; container.Items.Add(innerShape1); container.Items.Add(innerShape2); return container; }
Specify a FactoryItemTool that creates an instance of this container. Add this tool to a stencil:
void RegisterStencil() { var stencil = new DiagramStencil("CustomStencil", "Custom Shapes"); var itemTool = new FactoryItemTool( "CustomShape1", () => "Custom Shape 1", diagram => CreateContainerShape1(), new System.Windows.Size(200, 200), false ); stencil.RegisterTool(itemTool); DiagramToolboxRegistrator.RegisterStencil(stencil); diagramControl1.SelectedStencils = new StencilCollection() { "CustomStencil" }; }
Create Shapes Based on SVG Images
The DiagramControl
allows you to use SVG images as shapes. The code sample below demonstrates a basic example of how you can set up such a custom diagram item. For complete code and additional details on this item type, its settings, and limitations, refer to the following article: SVG Shapes.
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<circle cx="50" cy="50" r="40" stroke-width="4" stroke="blue" fill="green"/>
</svg>
void RegisterStencil() {
var stencil = new DiagramStencil("CustomStencil", "SVG Shapes");
System.IO.FileStream stream = System.IO.File.Open("..\\..\\greencircle.svg", System.IO.FileMode.Open);
var shapeDescription = DevExpress.Diagram.Core.ShapeDescription.CreateSvgShape(
shapeId: "SVGCircle",
name: "SVG Circle",
svgStream: stream,
getConnectionPoints: (s) => new[] { new System.Windows.Point(s.Width / 2, s.Height / 2) }
);
stencil.RegisterShape(shapeDescription);
DiagramToolboxRegistrator.RegisterStencil(stencil);
diagramControl1.SelectedStencils = new StencilCollection() { "CustomStencil" };
}
Use Templates to Create Custom Shapes and Containers
ShapeTemplate
and ContainerShapeTemplate
classes allow you to define shapes and containers in XAML (XML) and use them in the diagram. The code sample below demonstrates how to create a basic shape template. Refer to the following help topic for information on templates, available elements, and parameters: Use Templates to Create Custom Shapes and Containers.
<p:ResourceDictionary
xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns="http://schemas.devexpress.com/winfx/2008/xaml/diagram"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ShapeTemplate x:Key="{ShapeKey MyEllipse}" DefaultSize="120, 100">
<Start X="0" Y="0.5"/>
<Arc X="1" Y="0.5" Direction="Clockwise" Size="CreateSize(W/2,H/2)"/>
<Arc X="0" Y="0.5" Direction="Clockwise" Size="CreateSize(W/2,H/2)"/>
</ShapeTemplate>
</p:ResourceDictionary>
ResourceDictionary customShapesDictionary = new ResourceDictionary() {
Source = new Uri("CustomShapes.xaml", UriKind.Relative)
};
var stencil = DiagramStencil.Create(
"CustomStencil",
"Custom Shapes",
customShapesDictionary,
shapeName => shapeName
);
DiagramToolboxRegistrator.RegisterStencil(stencil);
diagramControl1.SelectedStencils = new StencilCollection() { "CustomStencil" };
Extend a Default Diagram Item
You can create diagram item descendants to extend default diagram items with additional properties. The code sample below demonstrates a basic example of such a custom diagram item. Refer to the following help topic for complete code, additional details, and limitations: Extend a Default Diagram Item.
public class CustomDiagramShape : DiagramShape {
[XtraSerializableProperty]
public string Description { get; set; }
static CustomDiagramShape() {
DiagramControl.ItemTypeRegistrator.Register(typeof(CustomDiagramShape));
}
}
void RegisterStencil() {
var stencil = new DevExpress.Diagram.Core.DiagramStencil("CustomStencil", "Custom Shapes");
var itemTool = new FactoryItemTool(
"CustomShape",
() => "Custom Shape",
diagram => {
CustomDiagramShape customShape = new CustomDiagramShape() { Width = 100, Height = 50 };
return customShape;
},
new Size(100, 50),
false
);
stencil.RegisterTool(itemTool);
DiagramToolboxRegistrator.RegisterStencil(stencil);
DiagramControl.ItemTypeRegistrator.Register(typeof(CustomDiagramShape));
}
void diagramControl_CustomGetEditableItemProperties(object sender, DiagramCustomGetEditableItemPropertiesEventArgs e) {
if (e.Item is CustomDiagramShape) {
e.Properties.Add(TypeDescriptor.GetProperties(typeof(CustomDiagramShape))["Description"]);
}
}
Additional Settings
Customize Appearance of Diagram Items
You can use common appearance customization techniques described in the following article: Modify Theme Resources. Use these techniques to display additional elements in an item that should not be saved to a document.
Serialize Complex Properties or a Complete Configuration for Custom Items
The DiagramControl
serialization mechanism requires that diagram item properties are serializable. If your custom item has complex or attached properties that cannot be serialized, use the following technique. Apply a style to your diagram item, specify required properties in the style, and assign the style key to the DiagramItem.CustomStyleId property. The DiagramControl
deserializes the CustomStyleId
key and re-applies the style when you load a diagram document or execute the undo action.