Back to Devexpress

Create Custom Diagram Items

wpf-404589-controls-and-libraries-diagram-control-diagram-items-create-custom-diagram-items.md

latest14.0 KB
Original Source

Create Custom Diagram Items

  • Feb 01, 2024
  • 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:

csharp
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" };
vb
Dim myStencil As DiagramStencil = New DiagramStencil("myStencil", "Custom Items")
myStencil.RegisterTool(New FactoryItemTool("customItem", Function() "Custom Item", Function(diagram) New DiagramImage() With {
    .Image = "img.png"
}, New Size(200, 30)))
DiagramToolboxRegistrator.RegisterStencil(myStencil)
Me.diagramControl1.SelectedStencils = New StencilCollection() From {"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.

View Example: Create Custom Shapes Based on Diagram Containers

  1. Create a container and add static non-selectable shapes:

  2. Specify a FactoryItemTool that creates an instance of this container. Add this tool to a stencil:

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.

xml
<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>
csharp
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" };
}
vb
Private Sub RegisterStencil()
    Dim stencil = New DiagramStencil("CustomStencil", "SVG Shapes")

    Dim stream As System.IO.FileStream = System.IO.File.Open("..\..\greencircle.svg", System.IO.FileMode.Open)

    Dim shapeDescription = DevExpress.Diagram.Core.ShapeDescription.CreateSvgShape(
        shapeId:="SVGCircle", 
        name:="SVG Circle", 
        svgStream:=stream, 
        getConnectionPoints:=Function(s) {New System.Windows.Point(s.Width / 2, s.Height / 2)}
    )

    stencil.RegisterShape(shapeDescription)
    DiagramToolboxRegistrator.RegisterStencil(stencil)

    diagramControl1.SelectedStencils = New StencilCollection() From {
        "CustomStencil"
    }
End Sub

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.

xaml
<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>
csharp
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" };
vb
Dim customShapesDictionary As ResourceDictionary = New ResourceDictionary() With {.Source = New Uri("CustomShapes.xaml", UriKind.Relative)}
Dim stencil = DiagramStencil.Create("CustomStencil", "Custom Shapes", customShapesDictionary, Function(shapeName) shapeName)
DiagramToolboxRegistrator.RegisterStencil(stencil)
Me.diagramControl1.SelectedStencils = New StencilCollection() From {"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.

csharp
public class CustomDiagramShape : DiagramShape {
    [XtraSerializableProperty]
    public string Description { get; set; }
    static CustomDiagramShape() {
        DiagramControl.ItemTypeRegistrator.Register(typeof(CustomDiagramShape));
    }
}
vb
Public Class CustomDiagramShape
    Inherits DiagramShape

    <XtraSerializableProperty>
    Public Property Description As String

    Shared Sub New()
        DiagramControl.ItemTypeRegistrator.Register(GetType(CustomDiagramShape))
    End Sub
End Class
csharp
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"]);
    }
}
vb
Private Sub RegisterStencil()
    Dim stencil = New DiagramStencil("CustomStencil", "Custom Shapes")
    Dim itemTool = New FactoryItemTool("CustomShape", Function() "Custom Shape", Function(diagram)
        Dim customShape As CustomDiagramShape = New CustomDiagramShape() With {.Width = 100, .Height = 50}
        Return customShape
    End Function, New Size(100, 50), False)
    stencil.RegisterTool(itemTool)
    DiagramToolboxRegistrator.RegisterStencil(stencil)
    DiagramControl.ItemTypeRegistrator.Register(GetType(CustomDiagramShape))
End Sub

Private Sub diagramControl_CustomGetEditableItemProperties(ByVal sender As Object, ByVal e As DiagramCustomGetEditableItemPropertiesEventArgs)
    If TypeOf e.Item Is CustomDiagramShape Then
        e.Properties.Add(TypeDescriptor.GetProperties(GetType(CustomDiagramShape))("Description"))
    End If
End Sub

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