Styling Shapes When Using GraphSource

This article describes which styles need to be applied when using a different ActiveTool of the RadDiagram when the GraphSource property is set.

For the purpose of this example, we will create the following ViewModels:

ContainerModel: A class deriving from the ContainerNodeViewModelBase ViewModel that represents a container node.

Model: A class deriving from the NodeViewModelBase ViewModel that represents a node.

Link: A class deriving from the LinkViewModelBase ViewModel that represents a link.

MyGraphSource: A class deriving from the ObservableGraphSourceBase ViewModel that represents the RadDiagram GraphSource.

Example 1: Creating the ViewModels

    public class ContainerModel : ContainerNodeViewModelBase<object>  
    {  
    }  
    public class Model : NodeViewModelBase  
    {         
    }  
    public class Link : LinkViewModelBase<NodeViewModelBase>  
    {         
    }  
    public class MyGraphSource : ObservableGraphSourceBase<NodeViewModelBase, Link> 
    { 
        public MyGraphSource() 
        {        
            ContainerModel containerModel = new ContainerModel() { Content = "Container Model", Position = new Point(250, 100) }; 
            Model model = new Model() 
            { 
                Content = "Custom Model", 
                Position = new Point(250, 100), 
            }; 
            containerModel.AddItem(model); 
            this.AddNode(containerModel);            
        }    
    }        

Next, we can go ahead and define a RadDiagram control in our view. We can add three buttons to change the ActiveTool property of the RadDiagram at runtime.

Example 2: Defining RadDiagram in XAML

    <Grid> 
        <Grid.RowDefinitions> 
            <RowDefinition Height="auto"/> 
            <RowDefinition Height="*"/> 
        </Grid.RowDefinitions> 
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10"> 
            <telerik:RadButton Content="Pointer Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Text Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Path Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Pencil Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Connector Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
        </StackPanel> 
        <telerik:RadDiagram x:Name="diagram" Grid.Row="1"/>  
    </Grid> 
And finally, we need to set the RadDiagram GraphSource property and subscribe to the Click event of the RadButtons. In the event handler, we are changing the ActiveTool property depending on the button content:

Example 3: Setting GraphSource property

    public MainWindow()  
    {  
        InitializeComponent();    
        this.diagram.GraphSource = new MyGraphSource();  
    }  
    private void RadButton_Click(object sender, RoutedEventArgs e) 
    { 
        var button = sender as RadButton; 
        switch (button.Content) 
        { 
            case "Pointer Tool": 
                this.diagram.ActiveTool = Telerik.Windows.Diagrams.Core.MouseTool.PointerTool; 
                break; 
            case "Path Tool": 
                this.diagram.ActiveTool = Telerik.Windows.Diagrams.Core.MouseTool.PathTool; 
                break; 
            case "Pencil Tool": 
                this.diagram.ActiveTool = Telerik.Windows.Diagrams.Core.MouseTool.PencilTool; 
                break; 
            case "Text Tool": 
                this.diagram.ActiveTool = Telerik.Windows.Diagrams.Core.MouseTool.TextTool; 
                break; 
            case "Connector Tool": 
                diagram.ActiveTool = Telerik.Windows.Diagrams.Core.MouseTool.ConnectorTool; 
                break; 
            default: 
                break; 
        } 
    } 
If you run the application now, the RadDiagram should display the following structure:

RadDiagram layout

Note that CustomShapes is the name of the project used in the example and this will be different on your end.

You can observe that the container and the shape inside does not show our custom text. By clicking on any of the buttons (without PointerTool) at the top you can see that every created shape displays the respective NodeViewModelBase class string.

RadDiagram without required styles

The different active tools correspond to different shapes:

  • TextTool: Creates a RadDiagramTextShape
  • PathTool: Creates a RadDiagramShape
  • PencilTool: Creates a RadDiagramShape
  • ConnectorTool: Creates a RadDiagramConnection

To overcome this you can create a StyleSelector and apply it to the ShapeStyleSelector of the RadDiagram. Example 4 demonstrates the custom StyleSelector.

Example 4: Creating a custom StyleSelector

    public class ShapeStyleSelector : StyleSelector 
    { 
        public Style ContainerStyle { get; set; } 
        public Style ShapeStyle { get; set; } 
        public Style TextToolShape { get; set; } 
        public override Style SelectStyle(object item, DependencyObject container) 
        { 
            if (container is RadDiagramContainerShape) 
            { 
                return ContainerStyle; 
            } 
 
            if (container is RadDiagramShape) 
            { 
                return ShapeStyle; 
            } 
 
            if(container is RadDiagramTextShape) 
            { 
                return TextToolShape; 
            } 
            return base.SelectStyle(item, container); 
        } 
    } 
Now you need to specify different styles for the different types of shapes. For example, when creating a shape with the TextTool, the TargetType property of the custom style needs to be set to RadDiagramTextShape. Example 4 shows the final XAML code.

Example 5: Creating custom styles for every shape

    <Window.Resources> 
        <DataTemplate x:Key="contentTemplate"> 
            <TextBlock Text="{Binding Content}" /> 
        </DataTemplate> 
        <DataTemplate x:Key="editTemplate"> 
            <TextBox Text="{Binding Content, Mode=TwoWay}" /> 
        </DataTemplate> 
        <local:ShapeStyleSelector x:Key="shapeStyleSelector" > 
            <local:ShapeStyleSelector.ContainerStyle> 
                <Style TargetType="telerik:RadDiagramContainerShape" BasedOn="{StaticResource RadDiagramContainerShapeStyle"> 
                    <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" /> 
                    <Setter Property="ContentTemplate" Value="{StaticResource contentTemplate}" /> 
                    <Setter Property="EditTemplate" Value="{StaticResource editTemplate}" /> 
                </Style> 
            </local:ShapeStyleSelector.ContainerStyle> 
            <local:ShapeStyleSelector.ShapeStyle> 
                <Style TargetType="telerik:RadDiagramShape" BasedOn="{StaticResource RadDiagramShapeStyle"> 
                    <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" /> 
                    <Setter Property="ContentTemplate" Value="{StaticResource contentTemplate}" /> 
                    <Setter Property="EditTemplate" Value="{StaticResource editTemplate}" /> 
                </Style> 
            </local:ShapeStyleSelector.ShapeStyle> 
            <local:ShapeStyleSelector.TextToolShape> 
                <Style TargetType="telerik:RadDiagramTextShape" BasedOn="{StaticResource RadDiagramTextShapeStyle"> 
                    <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" /> 
                    <Setter Property="ContentTemplate" Value="{StaticResource contentTemplate}"/> 
                    <Setter Property="EditTemplate" Value="{StaticResource editTemplate}"/> 
                </Style> 
            </local:ShapeStyleSelector.TextToolShape> 
        </local:ShapeStyleSelector> 
    </Window.Resources> 
    <Grid> 
        <Grid.RowDefinitions> 
            <RowDefinition Height="auto"/> 
            <RowDefinition Height="*"/> 
        </Grid.RowDefinitions> 
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10"> 
            <telerik:RadButton Content="Pointer Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Text Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Path Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Pencil Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            <telerik:RadButton Content="Connector Tool" Click="RadButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
        </StackPanel> 
        <telerik:RadDiagram x:Name="diagram" Grid.Row="1" 
            ConnectionEditTemplate="{StaticResource editTemplate}" 
            ConnectionTemplate="{StaticResource contentTemplate}"                    
            ShapeStyleSelector="{StaticResource shapeStyleSelector}"> 
        </telerik:RadDiagram> 
    </Grid> 
If you run the application now, the custom shapes created by the different tools will be displayed as expected.

RadDiagram with StyleSelector

See Also

In this article