Search
Tutorial 4: Custom Nodes Integration

This tutorial builds upon the OrgChartNode type from Tutorial 3. It shows how to fully integrate the custom type with other WpfDiagram features, such as serialization, undo support, creating nodes by drag-and-drop or drawing with the mouse on the canvas.

1. Add a NodeListView to the page and add a few OrgChartNode objects as its children:

Xaml  Copy Code

<Grid.Resources>
    <ResourceDictionary>
        <BitmapImage x:Key="img1" UriSource="016.png" />
        <BitmapImage x:Key="img2" UriSource="ac0026-64.png" />
    </ResourceDictionary>
</Grid.Resources>

<diag:NodeListView Width="150">
    <t:OrgChartNode
        Bounds="0,0,140,70"
        Title="CEO" FullName="Type here"
        Text="Chief executive officer"
        Image="{StaticResource img1}"
        />
    <t:OrgChartNode
        Bounds="0,0,140,70"
        Title="CIO" FullName="Type here"
        Text="Chief information officer"
        Image="{StaticResource img2}"
        />
</diag:NodeListView>

2. Add a copy constructor to the OrgChartNode class. The control throws an exception if you try to create via drag-and-drop an instance of a class without copy constructor:

C#  Copy Code

// Required for creating nodes by dragging them from the NodeListView
public OrgChartNode(OrgChartNode prototype) : base(prototype)
{
    Title = prototype.Title;
    FullName = prototype.FullName;
    Image = prototype.Image;
}

3. In order to enable drawing OrgChartNodes with the mouse, inherit the LinkNodesBehavior and override its CreateNode method. You could also inherit BehaviorBase or any of its derived classes, and override either CreateNode or StartDraw:

C#  Copy Code

public class OrgChartBehavior : LinkNodesBehavior
{
    public OrgChartBehavior(Diagram diagram) : base(diagram) { }

    protected override DiagramNode CreateNode()
    {
        return new OrgChartNode();
    }
}

4. Assign an instance of the behavior class to the CustomBehavior property of the DiagramView class:

C#  Copy Code

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // enable drawing OrgChartNodes with the mouse
    diagramView.CustomBehavior = new OrgChartBehavior(diagram);
}

5. To implement serialization of any new properties added by a custom item class, override the SaveToXml and LoadFromXml methods of the base DiagramItem class:

C#  Copy Code

// serialization support for custom properties

protected override void SaveToXml(XmlElement xmlElement, XmlPersistContext context)
{
    base.SaveToXml(xmlElement, context);
    context.WriteString(Title, "Title", xmlElement);
    context.WriteString(FullName, "FullName", xmlElement);
    context.WriteImage(Image, "Image", xmlElement);
}

protected override void LoadFromXml(XmlElement xmlElement, XmlPersistContext context)
{
    base.LoadFromXml(xmlElement, context);
    Title = context.ReadString("Title", xmlElement);
    FullName = context.ReadString("FullName", xmlElement);
    Image = context.ReadImage("Image", xmlElement);
}

6. Call the static RegisterItemClass method to assign an XML element name to the custom item type:

C#  Copy Code

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // enable serialization of the custom class
    Diagram.RegisterItemClass(typeof(OrgChartNode), "my:OrgChartNode", 1);

    // enable drawing OrgChartNodes with the mouse
    diagram.CustomBehavior = new OrgChartBehavior(diagram);
}

7. In order to enable undo / redo of changes done on OrgChartNode, create a DiagramItemProperties -derived class that contains member corresponding to the additional properties defined by OrgChartNode:

C#  Copy Code

public class OrgChartNodeProperties : DiagramNodeProperties
{
    internal string Title;
    internal string FullName;
    internal ImageSource Image;
}

8. Override the CreateProperties, SaveProperties and RestoreProperties methods:

C#  Copy Code

// undo and redo support

protected override DiagramItemProperties CreateProperties()
{
    return new OrgChartNodeProperties();
}

protected override void SaveProperties(DiagramItemProperties props)
{
    base.SaveProperties(props);

    var state = (OrgChartNodeProperties)props;
    state.Title = Title;
    state.FullName = FullName;
    state.Image = Image;
}

protected override void RestoreProperties(DiagramItemProperties props)
{
    base.RestoreProperties(props);

    var state = (OrgChartNodeProperties)props;
    Title = state.Title;
    FullName = state.FullName;
    Image = state.Image;
}

9. The full source code for this tutorial with several additional UI controls that invoke serialization and undo methods is available in the Samples\CSharp\Tutorial4 subfolder under the WpfDiagram installation folder.