Implement Semantic Zoom on a Shape level

This tutorial demonstrates how to implement custom semantic zoom on a RadDiagramShape level.

For the purpose of the tutorial we will use DataBinding and bind the RadDiagram GraphSource property to a collection of business objects. Then we will take advantage of the RadFluidContentControl to display three different contents inside each shape and we will make sure that the RadFluidContentControl.Content is changed based on the zoom factor of the RadDiagram.

Let's start with the ViewModels definitions. As the purpose of this example is to demonstrate a sample approach for implementing semantic zoom using the RadFluidContentControl, we will need one custom data class to describe the content of each shape. And as we need to change the information displayed in each shape along with the zoom factor applied in the RadDiagram, we will define a variety of properties in that class:

public class CustomNode : HierarchicalNodeViewModel 
{ 
    private ItemDisplayMode currentDisplayMode; 
    public ItemDisplayMode CurrentDisplayMode 
    { 
        get 
        { 
            return this.currentDisplayMode; 
        } 
        internal set 
        { 
            if (this.currentDisplayMode != value) 
            { 
                this.currentDisplayMode = value; 
                OnPropertyChanged("CurrentDisplayMode"); 
            } 
        } 
    } 
 
    public string Email { get; set; } 
 
    public string Phone { get; set; } 
 
    public string ImagePath { get; set; } 
 
    public string Address { get; set; } 
 
    public int HeadCount { get; set; } 
 
    public string JobPosition { get; set; } 
 
    public string FirstName { get; set; } 
 
    public string LastName { get; set; } 
 
    public CustomNode() 
    { 
        this.CurrentDisplayMode = ItemDisplayMode.Small; 
    } 
} 
 
public enum ItemDisplayMode 
{ 
    Medium, 
    Large, 
    Small 
} 
Public Class CustomNode 
    Inherits HierarchicalNodeViewModel 
    Private m_currentDisplayMode As ItemDisplayMode 
    Public Property CurrentDisplayMode() As ItemDisplayMode 
        Get 
            Return Me.m_currentDisplayMode 
        End Get 
        Friend Set(value As ItemDisplayMode) 
            If Me.m_currentDisplayMode <> value Then 
                Me.m_currentDisplayMode = value 
                OnPropertyChanged("CurrentDisplayMode") 
            End If 
        End Set 
    End Property 
 
    Public Property Email() As String 
        Get 
            Return m_Email 
        End Get 
        Set(value As String) 
            m_Email = Value 
        End Set 
    End Property 
    Private m_Email As String 
 
    Public Property Phone() As String 
        Get 
            Return m_Phone 
        End Get 
        Set(value As String) 
            m_Phone = Value 
        End Set 
    End Property 
    Private m_Phone As String 
 
    Public Property ImagePath() As String 
        Get 
            Return m_ImagePath 
        End Get 
        Set(value As String) 
            m_ImagePath = Value 
        End Set 
    End Property 
    Private m_ImagePath As String 
 
    Public Property Address() As String 
        Get 
            Return m_Address 
        End Get 
        Set(value As String) 
            m_Address = Value 
        End Set 
    End Property 
    Private m_Address As String 
 
    Public Property HeadCount() As Integer 
        Get 
            Return m_HeadCount 
        End Get 
        Set(value As Integer) 
            m_HeadCount = Value 
        End Set 
    End Property 
    Private m_HeadCount As Integer 
 
    Public Property JobPosition() As String 
        Get 
            Return m_JobPosition 
        End Get 
        Set(value As String) 
            m_JobPosition = Value 
        End Set 
    End Property 
    Private m_JobPosition As String 
 
    Public Property FirstName() As String 
        Get 
            Return m_FirstName 
        End Get 
        Set(value As String) 
            m_FirstName = Value 
        End Set 
    End Property 
    Private m_FirstName As String 
 
    Public Property LastName() As String 
        Get 
            Return m_LastName 
        End Get 
        Set(value As String) 
            m_LastName = Value 
        End Set 
    End Property 
    Private m_LastName As String 
 
    Public Sub New() 
        Me.CurrentDisplayMode = ItemDisplayMode.Small 
    End Sub 
End Class 
 
Public Enum ItemDisplayMode 
    Medium 
    Large 
    Small 
End Enum 

Next, let's build a sample collection of items to populate the RadDiagram.GraphSource:

public class MainViewModel : ViewModelBase 
{ 
    public ObservableGraphSourceBase<CustomNode, LinkViewModelBase<CustomNode>> Employees { get; set; } 
 
    public MainViewModel() 
    { 
        this.Employees = new ObservableGraphSourceBase<CustomNode, LinkViewModelBase<CustomNode>>(); 
        this.Employees.AddNode(new CustomNode() 
        { 
            FirstName = "Andrew", 
            LastName = "Fuller", 
            Email = "afuller@contoso.com", 
            Phone = "(205) 555 - 9898", 
            Address = "London, 120 Hanover Sq.", 
            Position = new Point(250, 250), 
            ImagePath = "/Images/AndrewFuller.jpg", 
            JobPosition = "CEO" 
        }); 
    } 
} 
Public Class MainViewModel 
    Inherits ViewModelBase 
 
    Public Property Employees() As ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode)) 
        Get 
            Return m_Employees 
        End Get 
        Set(value As ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode))) 
            m_Employees = Value 
        End Set 
    End Property 
    Private m_Employees As ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode)) 
 
    Public Sub New() 
        Me.Employees = New ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode))() 
        Me.Employees.AddNode(New CustomNode() With { 
                                                        .FirstName = "Andrew", 
                                                        .LastName = "Fuller", 
                                                        .Email = "afuller@contoso.com", 
                                                        .Phone = "(205) 555 - 9898", 
                                                        .Address = "London, 120 Hanover Sq.", 
                                                        .Position = New Point(250, 250), 
                                                        .ImagePath = "/Images/AndrewFuller.jpg", 
                                                        .JobPosition = "CEO" 
                                                    }) 
    End Sub 
End Class 

Now that our ViewModels are defined, we can start describing the View where the RadDiagram will be displayed. What we need is a RadDiagram instance which GraphSource property is data bound to the Employees collection. And in order to visualize the nodes in the diagram, we have to declare a DataTemplate. In this example, we will use a RadFluidContentControl to visualize the business data representing each node of our diagramming structure. And we will define the RadDiagramShape.ContentTemplate using the RadDiagram ShapeStyle property:

<Grid> 
    <telerik:RadDiagram x:Name="xDiagram" 
                        GraphSource="{Binding Employees}" 
                        Zoom="{Binding ZoomFactor, 
                                       Mode=TwoWay}"> 
        <telerik:RadDiagram.ShapeStyle> 
            <Style TargetType="telerik:RadDiagramShape"> 
                <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" /> 
                <Setter Property="Padding" Value="0" /> 
                <Setter Property="ContentTemplate"> 
                    <Setter.Value> 
                        <DataTemplate> 
                            <telerik:RadFluidContentControl Width="212" 
                                                            Height="74" 
                                                            ContentChangeMode="Manual"> 
                                <telerik:RadFluidContentControl.SmallContent> 
                                    <Grid> 
                                        <Grid.RowDefinitions> 
                                            <RowDefinition Height="2" /> 
                                            <RowDefinition Height="3" /> 
                                        </Grid.RowDefinitions> 
                                        <Grid HorizontalAlignment="Stretch" Background="{StaticResource MetroGray}" /> 
                                        <TextBlock x:Name="positionTextBlock" 
                                                   FontSize="14" 
                                                   Style="{StaticResource PositionTextBlockStyle}" 
                                                   Text="{Binding JobPosition}" /> 
 
                                        <StackPanel Grid.Row="1" 
                                                    Margin="10 0 0 0" 
                                                    Orientation="Horizontal"> 
                                            <TextBlock FontSize="21" 
                                                       Style="{StaticResource NameTextBlockStyle}" 
                                                       Text="{Binding FirstName}" /> 
                                            <TextBlock Margin="8 0 0 0" 
                                                       FontSize="21" 
                                                       Style="{StaticResource NameTextBlockStyle}" 
                                                       Text="{Binding LastName}" /> 
                                        </StackPanel> 
                                    </Grid> 
                                </telerik:RadFluidContentControl.SmallContent> 
                                <telerik:RadFluidContentControl.Content> 
                                    <Grid> 
                                        <Grid.RowDefinitions> 
                                            <RowDefinition Height="25" /> 
                                            <RowDefinition Height="49" /> 
                                        </Grid.RowDefinitions> 
                                        <Grid.ColumnDefinitions> 
                                            <ColumnDefinition Width="Auto" /> 
                                            <ColumnDefinition /> 
                                        </Grid.ColumnDefinitions> 
                                        <Grid Grid.Column="0" 
                                              Grid.ColumnSpan="2" 
                                              Width="212" 
                                              HorizontalAlignment="Stretch" 
                                              Background="{StaticResource MetroGray}" /> 
 
                                        <Grid Name="imageGrid" 
                                              Grid.RowSpan="2" 
                                              Width="65" 
                                              Background="Transparent"> 
                                            <Image Grid.RowSpan="2" 
                                                   Width="61" 
                                                   Height="70" 
                                                   Margin="2" 
                                                   Source="{Binding ImagePath}" 
                                                   Stretch="Fill" /> 
                                        </Grid> 
 
                                        <TextBlock Grid.Column="1" 
                                                   Margin="6 3 0 0" 
                                                   HorizontalAlignment="Left" 
                                                   Style="{StaticResource PositionTextBlockStyle}" 
                                                   Text="{Binding JobPosition}" /> 
 
                                        <Grid Name="nameAndHeadCountGrid" 
                                              Grid.Row="1" 
                                              Grid.Column="1"> 
                                            <Grid.RowDefinitions> 
                                                <RowDefinition Height="45" /> 
                                                <RowDefinition Height="55" /> 
                                            </Grid.RowDefinitions> 
                                            <StackPanel Orientation="Horizontal"> 
                                                <TextBlock Margin="6 5 0 0" 
                                                           Style="{StaticResource HeadCountTextBlockStyle}" 
                                                           Text="Headcount:" /> 
                                                <TextBlock Margin="3 5 0 0" 
                                                           Style="{StaticResource HeadCountTextBlockStyle}" 
                                                           Text="{Binding HeadCount}" /> 
                                            </StackPanel> 
                                            <StackPanel Grid.Row="1" Orientation="Horizontal"> 
                                                <TextBlock Margin="6 0 0 3" 
                                                           Style="{StaticResource NameTextBlockStyle}" 
                                                           Text="{Binding FirstName}" /> 
                                                <TextBlock Margin="5 0 0 3" 
                                                           Style="{StaticResource NameTextBlockStyle}" 
                                                           Text="{Binding LastName}" /> 
                                            </StackPanel> 
                                        </Grid> 
                                    </Grid> 
                                </telerik:RadFluidContentControl.Content> 
                                <telerik:RadFluidContentControl.LargeContent> 
                                    <Grid> 
                                        <Grid.RowDefinitions> 
                                            <RowDefinition Height="Auto" /> 
                                            <RowDefinition Height="Auto" /> 
                                            <RowDefinition Height="Auto" /> 
                                            <RowDefinition Height="" /> 
                                            <RowDefinition Height="" /> 
                                        </Grid.RowDefinitions> 
                                        <Grid.ColumnDefinitions> 
                                            <ColumnDefinition Width="Auto" /> 
                                            <ColumnDefinition Width="" /> 
                                        </Grid.ColumnDefinitions> 
 
                                        <Grid Grid.Column="0" 
                                              Grid.ColumnSpan="2" 
                                              HorizontalAlignment="Stretch" 
                                              Background="{StaticResource MetroGray}" /> 
 
                                        <TextBlock Grid.Column="1" 
                                                   Margin="4 3 0 0" 
                                                   FontSize="7" 
                                                   Style="{StaticResource PositionTextBlockStyle}" 
                                                   Text="{Binding JobPosition}" /> 
 
                                        <Grid Grid.Row="1" 
                                              Grid.RowSpan="2" 
                                              Grid.Column="1"> 
                                            <Grid.RowDefinitions> 
                                                <RowDefinition Height="0.45" /> 
                                                <RowDefinition Height="0.55*" /> 
                                            </Grid.RowDefinitions> 
                                            <StackPanel Orientation="Horizontal"> 
                                                <TextBlock Margin="4 3 0 0" 
                                                           FontSize="7" 
                                                           Style="{StaticResource HeadCountTextBlockStyle}" 
                                                           Text="Headcount:" /> 
                                                <TextBlock Margin="3 3 0 0" 
                                                           FontSize="7" 
                                                           Style="{StaticResource HeadCountTextBlockStyle}" 
                                                           Text="{Binding HeadCount}" /> 
                                            </StackPanel> 
                                            <StackPanel Grid.Row="1" 
                                                        Margin="4 0 0 3" 
                                                        VerticalAlignment="Center" 
                                                        Orientation="Horizontal"> 
                                                <TextBlock Margin="0" 
                                                           FontSize="9" 
                                                           Style="{StaticResource NameTextBlockStyle}" 
                                                           Text="{Binding FirstName}" /> 
                                                <TextBlock Margin="3 0 0 0" 
                                                           FontSize="9" 
                                                           Style="{StaticResource NameTextBlockStyle}" 
                                                           Text="{Binding LastName}" /> 
                                            </StackPanel> 
                                        </Grid> 
 
                                        <StackPanel Grid.Row="3" 
                                                    Grid.ColumnSpan="2" 
                                                    Margin="6,0,0,0" 
                                                    Orientation="Horizontal"> 
                                            <Viewbox Width="10.66" 
                                                     Height="8" 
                                                     Stretch="Fill"> 
                                                <Path HorizontalAlignment="Left" 
                                                      VerticalAlignment="Center" 
                                                      Data="M13.999998,3.7658489 L13.94845,3.803616 C12.542283,4.8337059 8.0308743,8.1299944 7.8814616,8.1299944 C7.7320304,8.1299944 3.3899567,4.9128594 2.0367067,3.907505 L2,3.8802307 L2,9.999999 L13.999998,9.999999 z M2.5423753,2.0000005 L7.8829308,6.0973635 L13.441984,2.0000005 z M0,0 L15.999998,0 L16,12 L1.1920929E-06,12 z" 
                                                      Fill="#FFEDEDED" 
                                                      Opacity="0.7" 
                                                      Stretch="Fill" 
                                                      UseLayoutRounding="False" /> 
                                            </Viewbox> 
 
                                            <TextBlock Margin="4 0 0 0" 
                                                       FontSize="7" 
                                                       Style="{StaticResource HeadCountTextBlockStyle}" 
                                                       Text="{Binding Email}" /> 
 
                                            <Viewbox Width="5.2" 
                                                     Height="8" 
                                                     Margin="20 0 0 0" 
                                                     Stretch="Fill"> 
                                                <Path HorizontalAlignment="Left" 
                                                      VerticalAlignment="Center" 
                                                      Data="M739.14526,183.75031 C739.14526,183.75031 736.72418,184.84114 736.49939,187.25047 C736.41388,188.16693 735.96222,188.58353 737.70624,193.2502 C739.12305,197.04138 740.83221,198.00002 742.37421,198.04219 C743.70874,198.07869 745.40796,197.68605 745.66803,197.16695 C745.96014,196.584 744.95941,194.33397 744.39557,193.87529 C744.07941,193.6181 743.83295,193.50031 743.08319,194.0009 C742.41235,194.44879 741.46832,194.96967 740.66663,194.08388 C739.98315,193.32875 738.70654,190.04181 738.93683,188.9693 C739.17474,187.86108 740.9682,187.82338 741.17651,187.40672 C741.38483,186.99005 741.02002,186.0629 740.08252,184.31284 C739.61816,183.44601 739.14526,183.75031 739.14526,183.75031 z" 
                                                      Fill="#FFEDEDED" 
                                                      Opacity="0.7" 
                                                      Stretch="Fill" 
                                                      UseLayoutRounding="False" /> 
                                            </Viewbox> 
 
                                            <TextBlock Margin="4 0 20 0" 
                                                       FontSize="7" 
                                                       Style="{StaticResource HeadCountTextBlockStyle}" 
                                                       Text="{Binding Phone}" /> 
                                        </StackPanel> 
 
                                        <StackPanel Grid.Row="4" 
                                                    Grid.ColumnSpan="2" 
                                                    Margin="6 0 0 3" 
                                                    Orientation="Horizontal"> 
                                            <Viewbox Width="9.85" 
                                                     Height="8" 
                                                     Stretch="Fill"> 
                                                <Path HorizontalAlignment="Left" 
                                                      VerticalAlignment="Center" 
                                                      Data="M3.0000026,7.0000038 L13.000003,7.0000038 L13.000003,9.0000038 L3.0000026,9.0000038 z M3.0000026,4.0000038 L13.000003,4.0000038 L13.000003,6.0000038 L3.0000026,6.0000038 z M2,2 L2,2.1666667 L2,10.833334 L2,11 L14,11 L14,10.833334 L14,2.1666667 L14,2 z M0,0 L16,0 L16,13 L0,13 z" 
                                                      Fill="#FFEDEDED" 
                                                      Opacity="0.7" 
                                                      Stretch="Fill" 
                                                      StrokeThickness="0" 
                                                      UseLayoutRounding="False" /> 
                                            </Viewbox> 
 
                                            <TextBlock Grid.Column="1" 
                                                       Margin="4 0 0 0" 
                                                       FontSize="7" 
                                                       Style="{StaticResource HeadCountTextBlockStyle}" 
                                                       Text="{Binding Address}" /> 
                                        </StackPanel> 
 
                                        <Grid Grid.RowSpan="3" 
                                              HorizontalAlignment="Left" 
                                              VerticalAlignment="Top" 
                                              Background="Transparent"> 
                                            <Viewbox Height="38.58" 
                                                     Margin="2" 
                                                     Stretch="Fill"> 
                                                <Image Source="{Binding ImagePath}" Stretch="Fill" /> 
                                            </Viewbox> 
                                        </Grid> 
                                    </Grid> 
                                </telerik:RadFluidContentControl.LargeContent> 
                            </telerik:RadFluidContentControl> 
                        </DataTemplate> 
                    </Setter.Value> 
                </Setter> 
            </Style> 
        </telerik:RadDiagram.ShapeStyle> 
    </telerik:RadDiagram> 
</Grid> 

In order to customize the appearance of each Content of the RadFluidContentControl, we can create a few custom styles. Please add the following in the Resources section of your View:

<Grid.Resources> 
    <SolidColorBrush x:Key="MetroGray" Color="#FFD0D0D0" /> 
    <Style x:Key="NameTextBlockStyle" TargetType="TextBlock"> 
        <Setter Property="FontFamily" Value="Segoe UI Light" /> 
        <Setter Property="FontSize" Value="17" /> 
        <Setter Property="Foreground" Value="{telerik:Windows8Resource ResourceKey=MainBrush}" /> 
        <Setter Property="VerticalAlignment" Value="Center" /> 
        <Setter Property="HorizontalAlignment" Value="Center" /> 
        <Setter Property="Margin" Value="2 0" /> 
    </Style> 
    <Style x:Key="PositionTextBlockStyle" TargetType="TextBlock"> 
        <Setter Property="FontFamily" Value="Sergoe UI" /> 
        <Setter Property="FontSize" Value="11" /> 
        <Setter Property="VerticalAlignment" Value="Center" /> 
        <Setter Property="HorizontalAlignment" Value="Left" /> 
        <Setter Property="Foreground" Value="#FF333333" /> 
        <Setter Property="Margin" Value="11 2 0 0" /> 
        <Setter Property="FontWeight" Value="Bold" /> 
    </Style> 
    <Style x:Key="HeadCountTextBlockStyle" TargetType="TextBlock" 
                    BasedOn="{StaticResource PositionTextBlockStyle}"> 
        <Setter Property="FontSize" Value="12" /> 
        <Setter Property="FontWeight" Value="Normal" /> 
    </Style> 
</Grid.Resources> 

Now that we have all prerequisites in place, we can start working on the semantic zoom logic. We need to bind the RadFluidContentControl State property to a business property in order to manually control it based on the RadDiagram Zoom. Now if you go back to the CustomNode class definition, you can see that we've defined a CurrentDisplayMode property and an ItemDisplayMode Enum to describe the current state of a RadDiagramShape. But in a real-life application, we will need to synchronize the state of all items so that they can change together. This is why we can create a business property in our MainViewModel that reflects the ItemDisplayMode of all RadDiagramShapes.

public ItemDisplayMode ItemsCurrentDisplayMode { get; set; }     
Private m_ItemsCurrentDisplayMode As ItemDisplayMode 
Public Property ItemsCurrentDisplayMode() As ItemDisplayMode 
    Get 
        Return m_ItemsCurrentDisplayMode 
    End Get 
    Set(value As ItemDisplayMode) 
        m_ItemsCurrentDisplayMode = Value 
    End Set 
End Property 

The essence of the semantic zoom discussed in this article, is to change the visual representation of the nodes based on the RadDiagram zoom. This is why we also need to define a business property to reflect the zoom factor in the MainViewModels. In the setter of the property, we will call a method that changes the ItemsCurrentDisplayMode value accordingly. In order to implement this logic we will also describe two static properties to act as thresholds - basically their values will determine the relation between the zoom factor and the ItemDisplayMode of our custom nodes. Please find below the complete definition of the MainViewModel class:

public class MainViewModel : ViewModelBase 
{ 
    private static double SmallToNormalTemplateThreshHold = 1.2d; 
    private static double NormallToLargeTemplateThreshHold = 2.1d; 
 
    public ObservableGraphSourceBase<CustomNode, LinkViewModelBase<CustomNode>> Employees { get; set; } 
 
    private double zoomFactor; 
    /// <summary> 
    ///     Gets or sets the zoom factor of the diagram. 
    /// </summary> 
    public double ZoomFactor 
    { 
        get 
        { 
            return this.zoomFactor; 
        } 
        internal set 
        { 
            if (this.zoomFactor != value) 
            { 
                this.zoomFactor = value; 
                this.OnZoomChanged(); 
                OnPropertyChanged("ZoomFactor"); 
            } 
        } 
    } 
    public ItemDisplayMode ItemsCurrentDisplayMode { get; set; } 
 
    public MainViewModel() 
    { 
        this.Employees = new ObservableGraphSourceBase<CustomNode, LinkViewModelBase<CustomNode>>(); 
        this.Employees.AddNode(new CustomNode() 
        { 
            FirstName = "Andrew", 
            LastName = "Fuller", 
            Email = "afuller@contoso.com", 
            Phone = "(205) 555 - 9898", 
            Address = "London, 120 Hanover Sq.", 
            Position = new Point(250, 250), 
            ImagePath = "/Images/AndrewFuller.jpg", 
            JobPosition = "CEO" 
        }); 
        this.ItemsCurrentDisplayMode = ItemDisplayMode.Medium; 
        this.ZoomFactor = 1; 
    } 
 
    private void OnZoomChanged() 
    { 
        ItemDisplayMode newMode; 
        if (SmallToNormalTemplateThreshHold < this.ZoomFactor && this.ZoomFactor <= NormallToLargeTemplateThreshHold) 
            newMode = ItemDisplayMode.Medium; 
        else if (this.ZoomFactor <= SmallToNormalTemplateThreshHold) 
            newMode = ItemDisplayMode.Small; 
        else 
            newMode = ItemDisplayMode.Large; 
 
        if (this.ItemsCurrentDisplayMode != newMode) 
            this.ChangeAllShapesDisplayMode(newMode); 
    } 
 
    private void ChangeAllShapesDisplayMode(ItemDisplayMode newMode) 
    { 
        this.ItemsCurrentDisplayMode = newMode; 
        foreach (var node in this.Employees.InternalItems) 
        { 
            node.CurrentDisplayMode = newMode; 
        } 
    } 
} 
Public Class MainViewModel 
    Inherits ViewModelBase 
    Private Shared SmallToNormalTemplateThreshHold As Double = 1.2 
    Private Shared NormallToLargeTemplateThreshHold As Double = 2.1 
 
    Public Property Employees() As ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode)) 
        Get 
            Return m_Employees 
        End Get 
        Set(value As ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode))) 
            m_Employees = Value 
        End Set 
    End Property 
    Private m_Employees As ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode)) 
 
    Private m_zoomFactor As Double 
    ''' <summary>''' 
    '''     Gets or sets the zoom factor of the diagram. 
    ''' </summary>''' 
    Public Property ZoomFactor() As Double 
        Get 
            Return Me.m_zoomFactor 
        End Get 
        Friend Set(value As Double) 
            If Me.m_zoomFactor <> value Then 
                Me.m_zoomFactor = value 
                Me.OnZoomChanged() 
                OnPropertyChanged("ZoomFactor") 
            End If 
        End Set 
    End Property 
    Private m_ItemsCurrentDisplayMode As ItemDisplayMode 
    Public Property ItemsCurrentDisplayMode() As ItemDisplayMode 
        Get 
            Return m_ItemsCurrentDisplayMode 
        End Get 
        Set(value As ItemDisplayMode) 
            m_ItemsCurrentDisplayMode = Value 
        End Set 
    End Property 
 
 
    Public Sub New() 
        Me.Employees = New ObservableGraphSourceBase(Of CustomNode, LinkViewModelBase(Of CustomNode))() 
        Me.Employees.AddNode(New CustomNode() With { 
                                                        .FirstName = "Andrew", 
                                                        .LastName = "Fuller", 
                                                        .Email = "afuller@contoso.com", 
                                                        .Phone = "(205) 555 - 9898", 
                                                        .Address = "London, 120 Hanover Sq.", 
                                                        .Position = New Point(250, 250), 
                                                        .ImagePath = "/Images/AndrewFuller.jpg", 
                                                        .JobPosition = "CEO" 
                                                    }) 
        Me.ItemsCurrentDisplayMode = ItemDisplayMode.Medium 
        Me.ZoomFactor = 1 
    End Sub 
 
    Private Sub OnZoomChanged() 
        Dim newMode As ItemDisplayMode 
        If SmallToNormalTemplateThreshHold < Me.ZoomFactor AndAlso Me.ZoomFactor <= NormallToLargeTemplateThreshHold Then 
            newMode = ItemDisplayMode.Medium 
        ElseIf Me.ZoomFactor <= SmallToNormalTemplateThreshHold Then 
            newMode = ItemDisplayMode.Small 
        Else 
            newMode = ItemDisplayMode.Large 
        End If 
 
        If Me.ItemsCurrentDisplayMode <> newMode Then 
            Me.ChangeAllShapesDisplayMode(newMode) 
        End If 
    End Sub 
 
    Private Sub ChangeAllShapesDisplayMode(newMode As ItemDisplayMode) 
        Me.ItemsCurrentDisplayMode = newMode 
        For Each node As var In Me.Employees.InternalItems 
            node.CurrentDisplayMode = newMode 
        Next 
    End Sub 
End Class 

Finally, we need to change the RadDiagram and RadFluidContentControl definitions to reflect the new properties. We will bind the RadDiagram.Zoom property to the MainViewModel ZoomFactor and the RadFluidContentControl State property to the CustomNode CurrentDisplayMode property. We can also apply a Transition on the RadFluidContentControl to animate the changes in the RadDiagramShape content.

<telerik:RadDiagram x:Name="xDiagram" 
                    GraphSource="{Binding Employees}" 
                    Zoom="{Binding ZoomFactor, 
                                   Mode=TwoWay}"> 
    <telerik:RadDiagram.ShapeStyle> 
        <Style TargetType="telerik:RadDiagramShape"> 
            <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" /> 
            <Setter Property="Padding" Value="0" /> 
            <Setter Property="ContentTemplate"> 
                <Setter.Value> 
                    <DataTemplate> 
                        <telerik:RadFluidContentControl Width="212" 
                                                        Height="74" 
                                                        ContentChangeMode="Manual" 
                                                        State="{Binding CurrentDisplayMode, 
                                                                        Converter={StaticResource ModeToStateConverter}}" 
                                                        TransitionDuration="0:0:0.3"> 
 
                            <telerik:RadFluidContentControl.Transition> 
                                <telerik:FadeTransition LayoutAnimation="Instant" /> 
                            </telerik:RadFluidContentControl.Transition> 
 
                            <telerik:RadFluidContentControl.SmallContent> 
                                //Small Content 
                            </telerik:RadFluidContentControl.SmallContent> 
                            <telerik:RadFluidContentControl.Content> 
                                //Content 
                            </telerik:RadFluidContentControl.Content> 
                            <telerik:RadFluidContentControl.LargeContent> 
                                //Large Content 
                             </telerik:RadFluidContentControl.LargeContent> 
                        </telerik:RadFluidContentControl> 
                    </DataTemplate> 
                </Setter.Value> 
            </Setter> 
        </Style> 
    </telerik:RadDiagram.ShapeStyle> 
</telerik:RadDiagram> 

If you run the application now, you should be able to dynamically change the content of the sample RadDiagramShape while zooming in or out of the RadDiagram. Rad Diagram Semantic Zoom Fluid Content

A semantic zoom feature is implemented in the OrgChart demo solution.

In this article