I was looking to implement Silverlight Telerik Transitions in my Silverlight 5 application with User Controls to walk a user through a wizard. My initial approach was to use a Visual State Manager, which would allow me to keep all the UI logic in the XAML. This did not work well with Telerik Transitions. I decided to use DataTriggers that modified the state of the UI based on a WizardState enumeration on my View Model.
View Model
Namespace ViewModels.Employee
Public Class EmployeeViewModel
Inherits BaseViewModel
#Region "Properties"
Private _employeeSetupState As EmployeeSetupStateEnum
Public Property EmployeeSetupState As EmployeeSetupStateEnum
Get
Return _employeeSetupState
End Get
Set(ByVal value As EmployeeSetupStateEnum)
If _employeeSetupState <> value Then
_employeeSetupState = value
NotifyPropertyChanged("CanMoveForward")
NotifyPropertyChanged("CanMoveBack")
NotifyPropertyChanged("EmployeeSetupState")
End If
End Set
End Property
Public ReadOnly Property CanMoveForward() As Boolean
Get
Dim newState As Integer = EmployeeSetupState + 1
If [Enum].IsDefined(GetType(EmployeeSetupStateEnum), newState) Then
Return True
End If
Return False
End Get
End Property
Public ReadOnly Property CanMoveBack() As Boolean
Get
Dim newState As Integer = EmployeeSetupState - 1
If [Enum].IsDefined(GetType(EmployeeSetupStateEnum), newState) Then
Return True
End If
Return False
End Get
End Property
' The Properties for the View Models are defined here.
#End Region
#Region "Base Overrides/Overloads"
Public Overrides Sub Initialize()
MyBase.Initialize()
EmployeeSetupState = 0
InitializeStep()
End Sub
#End Region
#Region "Public Methods"
Public Sub NextStep()
If CanMoveForward Then
EmployeeSetupState = CType(EmployeeSetupState + 1, EmployeeSetupStateEnum)
InitializeStep()
End If
End Sub
Public Sub PreviousStep()
If CanMoveBack Then
EmployeeSetupState = CType(EmployeeSetupState - 1, EmployeeSetupStateEnum)
InitializeStep()
End If
End Sub
#End Region
#Region "Private Methods"
Private Sub InitializeStep()
Select Case EmployeeSetupState
Case EmployeeSetupStateEnum.EmployeeGeneralInformationState
EmployeeGeneralInformationViewModel.Initialize()
Case EmployeeSetupStateEnum.EmployeeAddressInformationState
EmployeeAddressInformationViewModel.Initialize()
Case EmployeeSetupStateEnum.EmployeeContactInformationState
EmployeeContactInformationViewModel.Initialize()
Case EmployeeSetupStateEnum.EmployeeCommentsState
EmployeeCommentsViewModel.Initialize()
End Select
End Sub
#End Region
End Class
''' <summary>
''' States of the Employee setup process. These steps
''' are executed in the order specified.
''' </summary>
''' <remarks></remarks>
Public Enum EmployeeSetupStateEnum
EmployeeGeneralInformationState
EmployeeAddressInformationState
EmployeeContactInformationState
EmployeeCommentsState
End Enum
End Namespace
In the code above, I have an enumeration that specifies valid states for my employee setup process (specified in the order I want to show these states) and a property in my View Model that holds the current state of the employee setup process. I have a trigger that calls the Initialize() method on my View Model when the page loads. During the initialization process, my EmployeeSetupState is set to the first step and the view model for that step is initialized by calling the InitializeStep() method. I have a property that determines if the current EmployeeSetupState has a previous or next step. My View Model also holds a reference to the View Models for each of the User Controls that make up my employee setup states (not shown in the code above).
View
<UserControl.Resources>
<vm:EmployeeViewModel x:Name="ViewModel"/>
</UserControl.Resources>
<Grid xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="250" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<ic:CallMethodAction MethodName="Initialize"
TargetObject="{Binding Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<telerik:RadTransitionControl Content="{Binding EmployeeSetupState}">
<telerik:RadTransitionControl.Transition>
<telerik:FadeTransition />
</telerik:RadTransitionControl.Transition>
<telerik:RadTransitionControl.ContentTemplate>
<DataTemplate>
<Grid Margin="5,10,5,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<uc:EmployeeGeneralInformationView x:Name="EmployeeGeneralInformationView"
Visibility="Collapsed"
DataContext="{Binding Source=ViewModel, Path=EmployeeGeneralInformationViewModel, Mode=TwoWay}" />
<uc:EmployeeAddressInformationView x:Name="EmployeeAddressInformationView"
Visibility="Collapsed"
DataContext="{Binding Source=ViewModel, Path=EmployeeAddressInformationViewModel, Mode=TwoWay}" />
<uc:EmployeeContactInformationView x:Name="EmployeeContactInformationView"
Visibility="Collapsed"
DataContext="{Binding Source=ViewModel, Path=EmployeeContactInformationViewModel, Mode=TwoWay}" />
<uc:EmployeeCommentsView x:Name="EmployeeCommentsView"
Visibility="Collapsed"
DataContext="{Binding Source=ViewModel, Path=EmployeeCommentsViewModel, Mode=TwoWay}" />
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding Converter={StaticResource EnumToStringConverter}}"
Value="EmployeeGeneralInformationState">
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Visible"
TargetName="EmployeeGeneralInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeAddressInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeContactInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeCommentsView" />
</ei:DataTrigger>
<ic:DataTrigger Binding="{Binding Converter={StaticResource EnumToStringConverter}}"
Value="EmployeeAddressInformationState">
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeGeneralInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Visible"
TargetName="EmployeeAddressInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeContactInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeCommentsView" />
</ic:DataTrigger>
<ic:DataTrigger Binding="{Binding Converter={StaticResource EnumToStringConverter}}"
Value="EmployeeContactInformationState">
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeGeneralInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeAddressInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Visible"
TargetName="EmployeeContactInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeCommentsView" />
</ic:DataTrigger>
<ic:DataTrigger Binding="{Binding Converter={StaticResource EnumToStringConverter}}"
Value="EmployeeCommentsState">
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeGeneralInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeAddressInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Collapsed"
TargetName="EmployeeContactInformationView" />
<ic:ChangePropertyAction
PropertyName="Visibility" Value="Visible"
TargetName="EmployeeCommentsView" />
</ic:DataTrigger>
</i:Interaction.Triggers>
</Grid>
</DataTemplate>
</telerik:RadTransitionControl.ContentTemplate>
</telerik:RadTransitionControl>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="PreviousButton" Content="< Previous" HorizontalAlignment="Right"
Visibility="{Binding CanMoveBack, Converter={StaticResource BoolToVisibilityConverter}}"
Margin="5" Style="{StaticResource ButtonPrimaryStyle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ic:CallMethodAction MethodName="PreviousStep"
TargetObject="{Binding Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button x:Name="NextButton" Content="Next >" Width="70" HorizontalAlignment="Right"
Visibility="{Binding CanMoveForward, Converter={StaticResource BoolToVisibilityConverter}}"
Margin="5" Style="{StaticResource ButtonPrimaryStyle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ic:CallMethodAction MethodName="NextStep"
TargetObject="{Binding Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</Grid>
In my View, I bind the Content property of RadTransitionControl to the EmployeeSetupState from my View Model. The transitions happen each time the state change occurs. The data triggers control what view displays depending on the current employee setup state. In the data triggers I use the ChangePropertyAction to set the Visibility of the User Controls. This separates my View Model code to only determine and set the state of the setup process and my View handles the display.