Edit this page

Place RadControls in Diagram Shapes

This tutorial demonstrates how to use UI for WPF in the content of a RadDiagramShape component.

As the RadDiagramShape essentially derives from a ContentControl, its Content can wrap other controls. For the purpose of this tutorial we will use a RadCalendar and a RadGridView and will display both in RadDiagramShapes. We will also connect these shapes with a RadDiagramConnection.

Let's start by defining a RadDiagram instance in our view:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <TextBlock HorizontalAlignment="Center" Text="Hosting Telerik controls in shapes" />
    <telerik:RadDiagram x:Name="diagram" 
                        Grid.Row="1" 
                        Grid.RowSpan="1" 
                        ActiveTool="PointerTool" 
                        Background="White"
                        IsBackgroundSurfaceVisible="false" 
                        Zoom="1">
    </telerik:RadDiagram>
</Grid>

Next, we can add a RadDiagramShape that contains a RadGridView component. We will define these controls in our XAML view:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <TextBlock HorizontalAlignment="Center" Text="Hosting Telerik controls in shapes" />
    <telerik:RadDiagram x:Name="diagram" 
                        Grid.Row="1" 
                        Grid.RowSpan="1" 
                        ActiveTool="PointerTool" 
                        Background="White"
                        IsBackgroundSurfaceVisible="false" 
                        Zoom="1">
        <telerik:RadDiagramShape x:Name="gridShape" 
                                Position="600,50" 
                                UseGlidingConnector="true"
                                HorizontalContentAlignment="Stretch" 
                                VerticalContentAlignment="Stretch">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="30" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <TextBlock Text="Dragging area" HorizontalAlignment="Center" FontSize="16" />
                <telerik:RadGridView ItemsSource="{Binding}" 
                                    Grid.Row="1" 
                                    Background="LightBlue"
                                    BorderBrush="SteelBlue" />
            </Grid>
        </telerik:RadDiagramShape>
    </telerik:RadDiagram>
</Grid>

If you run the solution at this point, you should get the following diagramming structure:
raddiagram-howto-radcontrols-empty-gridview

And as our RadGridView is currently empty, we can go ahead and populate it with sample data. For that purpose, we first need to define a custom data class - let's name it ProductSales:

public class ProductSales
{
    public ProductSales(int quantity, int month, string monthName)
    {
        this.Quantity = quantity;
        this.Month = month;
        this.MonthName = monthName;
    }

    public int Quantity { get; set; }
    public int Month { get; set; }
    public string MonthName { get; set; }
}
Public Class ProductSales
    Public Sub New(quantity As Integer, month As Integer, monthName As String)
        Me.Quantity = quantity
        Me.Month = month
        Me.MonthName = monthName
    End Sub

    Public Property Quantity() As Integer
        Get
            Return m_Quantity
        End Get
        Set(value As Integer)
            m_Quantity = Value
        End Set
    End Property
    Private m_Quantity As Integer
    Public Property Month() As Integer
        Get
            Return m_Month
        End Get
        Set(value As Integer)
            m_Month = Value
        End Set
    End Property
    Private m_Month As Integer
    Public Property MonthName() As String
        Get
            Return m_MonthName
        End Get
        Set(value As String)
            m_MonthName = Value
        End Set
    End Property
    Private m_MonthName As String
End Class

Next in our code-behind we can create a method that returns a list of ProductSales and use its result as a DataContext of the view:

private static List<ProductSales> GetProductSales()
{
    var persons = new List<ProductSales>
    {
        new ProductSales(154, 1, "January"), 
        new ProductSales(138, 2, "February"), 
        new ProductSales(143, 3, "March"), 
        new ProductSales(120, 4, "April"), 
        new ProductSales(135, 5, "May"), 
        new ProductSales(125, 6, "June"), 
        new ProductSales(179, 7, "July"), 
        new ProductSales(170, 8, "August"), 
        new ProductSales(198, 9, "September"), 
        new ProductSales(187, 10, "October"), 
        new ProductSales(193, 11, "November"), 
        new ProductSales(212, 12, "December")
    };
    return persons;
}
public Example()
{
    InitializeComponent();
    this.DataContext = GetProductSales();
}
Private Shared Function GetProductSales() As List(Of ProductSales)
    Dim persons = New List(Of ProductSales)() From {
        New ProductSales(154, 1, "January"),
        New ProductSales(138, 2, "February"),
        New ProductSales(143, 3, "March"),
        New ProductSales(120, 4, "April"),
        New ProductSales(135, 5, "May"),
        New ProductSales(125, 6, "June"),
        New ProductSales(179, 7, "July"),
        New ProductSales(170, 8, "August"),
        New ProductSales(198, 9, "September"),
        New ProductSales(187, 10, "October"),
        New ProductSales(193, 11, "November"),
        New ProductSales(212, 12, "December")
    }
    Return persons
End Function
Public Sub New()
    InitializeComponent()
    Me.DataContext = GetProductSales()
End Sub

Now if we run the solution we will have a populated RadGridView control inside the RadDiagramShape.
raddiagram-howto-radcontrols-gridview

We can also define a shape in the code-behind file and set its content to any RadControl. Please have a look at the example below as it demonstrates how to create a RadDiagramShape and use a RadCalendar in its Content:

public Example()
{
    InitializeComponent();
    this.DataContext = GetProductSales();
    this.Loaded += this.OnLoaded;
}

private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
    // the alternative to this code approach is to set the ContentTemplate in XAML
    // See the documentation on this - http://www.telerik.com/help/wpf/raddiagrams-features-shapes.html&#13;    var calendar = new RadDiagramShape()
    {
        Position = new Point(20, 150),
        Content = new RadCalendar { SelectedDate = DateTime.Now.AddDays(254), Margin = new Thickness(10) },
        Background = new SolidColorBrush(Colors.Blue),
        BorderBrush = new SolidColorBrush(Colors.DarkGray),
        BorderThickness = new Thickness(1),
        UseGlidingConnector = true,
        HorizontalContentAlignment = HorizontalAlignment.Stretch,
        VerticalContentAlignment = VerticalAlignment.Stretch
    };
    this.diagram.AddShape(calendar);
}
Public Sub New()
    InitializeComponent()
    Me.DataContext = GetProductSales()
    AddHandler Me.Loaded, AddressOf Me.OnLoaded
End Sub

Private Sub OnLoaded(sender As Object, routedEventArgs As RoutedEventArgs)
    ' the alternative to this code approach is to set the ContentTemplate in XAML '
    ' See the documentation on this - http://www.telerik.com/help/wpf/raddiagrams-features-shapes.html '
    Dim calendar = New RadDiagramShape() With {
            .Position = New Point(20, 150),
            .Content = New RadCalendar() With
                        {
                            .SelectedDate = DateTime.Now.AddDays(254),
                            .Margin = New Thickness(10)
                        },
            .Background = New SolidColorBrush(Colors.Blue),
            .BorderBrush = New SolidColorBrush(Colors.DarkGray),
            .BorderThickness = New Thickness(1),
            .UseGlidingConnector = True,
            .HorizontalContentAlignment = HorizontalAlignment.Stretch,
            .VerticalContentAlignment = VerticalAlignment.Stretch
    }
    Me.diagram.AddShape(calendar)
End Sub

Running the project now should display two shapes within the RadDiagram instance:
raddiagram-howto-radcontrols

Finally, we can connect these shapes using a single connection. Let's set it up in the OnLoaded() method implementation:

private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
    // the alternative to this code-approach is to set the ContentTemplate in XAML
    // See the documentation on this, http://www.telerik.com/help/wpf/raddiagrams-features-shapes.html&#13;    var calendar = new RadDiagramShape()
    {
        //...
    };
    this.diagram.AddShape(calendar);

    var con = this.diagram.AddConnection(this.diagram.Shapes[1], this.diagram.Shapes[0]) as RadDiagramConnection;
    con.Content = "Corresponds to";
    con.SourceCapType = CapType.Arrow6Filled;
    con.TargetCapType = CapType.Arrow2Filled;
}
Private Sub OnLoaded(sender As Object, routedEventArgs As RoutedEventArgs) '
    ' the alternative to this code-approach is to set the ContentTemplate in XAML '
    ' See the documentation on this, http://www.telerik.com/help/wpf/raddiagrams-features-shapes.html&#13;    Dim calendar = New RadDiagramShape() From {
                                                ...
                                              }
    Me.diagram.AddShape(calendar)

    Dim con = TryCast(Me.diagram.AddConnection(Me.diagram.Shapes(1), Me.diagram.Shapes(0)), RadDiagramConnection)
    con.Content = "Corresponds to"
    con.SourceCapType = CapType.Arrow6Filled
    con.TargetCapType = CapType.Arrow2Filled
End Sub

raddiagram-howto-radcontrols-link

You can download a runnable project of the demonstrated example from our online SDK repository here, after navigating to Diagram/ControlShape.