Skip to main content
All docs
V24.1

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

The code example below does the following:

Add Predefined Diagram Image

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" };

View Example: Register FactoryItemTools for Regular and Custom Shapes

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.

WPF Diagram - DiagramContainer Shape

View Example: Create Custom Shapes Based on Diagram Containers

  1. 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;
    }
    
  2. 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.

WPF Diagram - 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" };
}

View Example: Register and Use SVG Shapes

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.

Use Shape Templates

<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" };

View Example: Create Custom Shapes with Connection Points

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.

Create a DiagramShape Descendant

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"]);
    }
}

View Example: Create a DiagramShape Descendant with Editable and Serializable Properties

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.

Examples