New to Telerik UI for WPF? Download free 30-day trial

How to Exclude Shapes from Serialization

The following article will demonstrate how to exclude shapes from serialization.

With the 2024 Q3 SP1 release, the RadDiagram control requires registering the custom types of shapes, connections, and connectors, in order to deserialize them successfully. Read more about this change here.

For the purpose of this example, we will create the following view models.

  • Node: A class deriving from the NodeViewModelBase class that represents a node. The class will implement two additional properties: bool IsStatic and Guid ID. The serialization of the shapes will depends on the first property. The Guid property will be returned in the GetNodeUniqueId() to cache the serialized shapes and connections.

  • Link: A class deriving from the LinkViewModelBase that represent a connection.

  • MyGraphSource: A class deriving from the SerializableGraphSourceBase class that represent the RadDiagram GraphSource.

Example 1: Creating view models

public class Node : NodeViewModelBase 
{ 
    public bool IsStatic { get; set; } 
    public Guid Id { get; set; } 
} 
public class Link : LinkViewModelBase<NodeViewModelBase> 
{ 
} 
public class MyGraphSource : SerializableGraphSourceBase<Node, Link> 
{        
    public MyGraphSource() 
    { 
        Node saveShape = new Node() { Content = "Shape 1", Position = new System.Windows.Point(122, 122) }; 
        Node notSaveShape = new Node() { Content = "Shape 2", Position = new System.Windows.Point(500, 100), IsStatic = true }; 
        this.AddNode(saveShape); 
        this.AddNode(notSaveShape); 
    } 
 
    public override string GetNodeUniqueId(Node node) 
    { 
        return node.Id.ToString(); 
    } 
 
    public override void SerializeNode(Node node, Telerik.Windows.Diagrams.Core.SerializationInfo info) 
    { 
        base.SerializeNode(node, info); 
        info["Content"] = node.Content; 
        info["IsStatic"] = node.IsStatic; 
    } 
 
    public override Node DeserializeNode(Telerik.Windows.Diagrams.Core.IShape shape, Telerik.Windows.Diagrams.Core.SerializationInfo info) 
    { 
        base.DeserializeNode(shape, info); 
        if (info["Content"] != null) 
        { 
            return new Node() 
            { 
                Content = info["Content"].ToString(), 
                IsStatic = info["IsStatic"].ToString() == "true" ? true : false 
            }; 
        } 
        return null; 
    } 
} 
Next to exclude a shape from serialization, create a custom class which derives from SerializationService and override the SerializeShapes method. Inside the method you can create custom logic to filter which shapes to be serialize and pass it to the base.SerializeShapes() method.

Example 2: Creating custom SerializationService

public class CustomSerializationService : SerializationService 
{ 
    public CustomSerializationService(IGraphInternal graph) : base(graph) { } 
 
    public override XElement SerializeShapes(IEnumerable<IShape> shapes) 
    { 
        var filteredShapes = shapes.Where(x => 
                x is RadDiagramShape && 
                (x as RadDiagramShape).DataContext is Node && 
                ((x as RadDiagramShape).DataContext as Node).IsStatic == false); 
 
        return base.SerializeShapes(filteredShapes); 
    } 
} 
Next, define a RadDiagram control in the Xaml view. We'll keep it simple - two buttons for save and load and a diagram with two shapes.

Example 2: Defining RadDiagram in XAML

<Grid> 
    <Grid.RowDefinitions> 
        <RowDefinition Height="Auto" /> 
        <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 
    <StackPanel HorizontalAlignment="Right"> 
        <Button Content="Save" Command="telerik:DiagramCommands.Save" /> 
        <Button Content="Load" Command="telerik:DiagramCommands.Open" /> 
    </StackPanel> 
    <Grid Grid.Row="1"> 
        <telerik:RadDiagram x:Name="diagram"   > 
            <telerik:RadDiagram.ShapeTemplate> 
                <DataTemplate> 
                    <TextBlock Text="{Binding Content}"/> 
                </DataTemplate> 
            </telerik:RadDiagram.ShapeTemplate> 
            <telerik:RadDiagram.ShapeStyle> 
                <Style TargetType="telerik:RadDiagramShape"> 
                    <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" /> 
                    <Setter Property="Content" Value="{Binding Content}"/> 
                </Style> 
            </telerik:RadDiagram.ShapeStyle> 
        </telerik:RadDiagram> 
    </Grid> 
</Grid> 
Finally, set the RadDiagram GraphSource property, register the custom SerializationService class and override the Open and Save commands from the DiagramCommands class. Then using the DiagramExtension FileManager class you can export the diagram into a file and load it again from it.

Example 2: Register the custom SerializationService

public partial class MainWindow : Window 
{ 
    private FileManager fileManager; 
    public MainWindow() 
    { 
        InitializeComponent(); 
        this.diagram.GraphSource = new MyGraphSource(); 
        this.fileManager = new FileManager(this.diagram); 
        this.diagram.ServiceLocator.Register<ISerializationService>(new CustomSerializationService(this.diagram)); 
    } 
 
    static MainWindow() 
    { 
        var saveBinding = new CommandBinding(DiagramCommands.Save, ExecuteSave); 
        var openBinding = new CommandBinding(DiagramCommands.Open, ExecuteOpen); 
 
        CommandManager.RegisterClassCommandBinding(typeof(MainWindow), saveBinding); 
        CommandManager.RegisterClassCommandBinding(typeof(MainWindow), openBinding); 
    } 
 
    private static void ExecuteOpen(object sender, ExecutedRoutedEventArgs e) 
    { 
        var owner = sender as MainWindow; 
        if (owner != null) 
        { 
            owner.diagram.Clear(); 
            owner.fileManager.LoadFromFile();                
        } 
    } 
 
    private static void ExecuteSave(object sender, ExecutedRoutedEventArgs e) 
    { 
        var owner = sender as MainWindow; 
        if (owner != null) 
        { 
            owner.fileManager.SaveToFile(); 
        }                
    } 
} 

See Also

In this article