Thursday, 31 May 2018

Xamarin.Forms Behaviors: GoToStateAction

Previously, I mentioned that I’d published v1.4 of my Behaviors library, and that it included some new functionality. The main item of new functionality is a GoToStateAction class, which represents an action that will transition a VisualElement to a specified VisualState when triggered. It requires you to set a TargetObject property to the VisualElement that contains the VisualState, and a StateName property to the name of the VisualState to be transitioned to.

In this blog post, I’ll explain how to use the GoToStateAction class with both the EventHandlerBehavior and the DataChangedBehavior.

Transitioning to a VisualState when an Event Fires

The following code example shows an example of using the EventHandlerBehavior and GoToStateAction classes to transition a VisualElement to a specified VisualState when an event fires:

<StackLayout> <Label Text="Goto VisualState when Event Fires" FontAttributes="Bold" HorizontalOptions="Center" /> <Label Text="Select an item in the Picker:" /> <Picker x:Name="picker" Title="Colours"> <Picker.Items> <x:String>Red</x:String> <x:String>Blue</x:String> <x:String>Green</x:String> </Picker.Items> <Picker.Behaviors> <behaviors:EventHandlerBehavior EventName="SelectedIndexChanged"> <behaviors:GoToStateAction StateName="PickerItemSelected" TargetObject="{x:Reference stackLayout}" /> </behaviors:EventHandlerBehavior> </Picker.Behaviors> </Picker> <Label Text="Selecting an item in the Picker will enable content below." /> </StackLayout> <local:Separator /> <StackLayout x:Name="stackLayout" IsVisible="false"> <VisualStateManager.VisualStateGroups> <VisualStateGroup Name="PickerStates"> <VisualState Name="PickerItemSelected"> <VisualState.Setters> <Setter Property="IsVisible" Value="true" /> </VisualState.Setters> </VisualState> <VisualState Name="None" /> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Label Text="Goto VisualState when Data Changes" FontAttributes="Bold" HorizontalOptions="Center" /> ... </StackLayout>

When the user selects an item in the Picker, the SelectedIndexChanged event fires. The EventHandlerBehavior listens for this event to occur, and executes the GoToStateAction in response. The GoToStateAction causes the TargetObject (stackLayout) to transition to the StateName (PickerItemSelected). In this contrived example, this causes all of the views in the StackLayout named stackLayout to become visible.

Transitioning to a VisualState when Data Changes

The following code example shows an example of using the DataChangedBehavior and GoToStateAction classes to transition a VisualElement to a specified VisualState when data changes:

<Entry x:Name="entry" FontSize="Large" Margin="30, 0, 0, 0"> <Entry.Behaviors> <behaviors:DataChangedBehavior Binding="{Binding Path=Text, Source={x:Reference entry}}" ComparisonCondition="NotEqual" Value="Xamarin"> <behaviors:GoToStateAction StateName="Invalid" TargetObject="{x:Reference helpLabel}" /> <behaviors:GoToStateAction StateName="Invalid" TargetObject="{x:Reference submitButton}" /> </behaviors:DataChangedBehavior> <behaviors:DataChangedBehavior Binding="{Binding Path=Text, Source={x:Reference entry}}" ComparisonCondition="Equal" Value="Xamarin"> <behaviors:GoToStateAction StateName="Valid" TargetObject="{x:Reference helpLabel}" /> <behaviors:GoToStateAction StateName="Valid" TargetObject="{x:Reference submitButton}" /> </behaviors:DataChangedBehavior> </Entry.Behaviors> </Entry> <Label x:Name="helpLabel" Text="Enter Xamarin (case sensitive) in the entry above."> <VisualStateManager.VisualStateGroups> <VisualStateGroup Name="ValidityStates"> <VisualState Name="Valid"> <VisualState.Setters> <Setter Property="TextColor" Value="Transparent" /> </VisualState.Setters> </VisualState> <VisualState Name="Invalid" /> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Label> <Button x:Name="submitButton" Text="Submit" IsEnabled="false" FontSize="Large" Margin="0, 20" VerticalOptions="Center" HorizontalOptions="Center"> <VisualStateManager.VisualStateGroups> <VisualStateGroup Name="ValidityStates"> <VisualState Name="Valid"> <VisualState.Setters> <Setter Property="IsEnabled" Value="True" /> </VisualState.Setters> </VisualState> <VisualState Name="Invalid"> <VisualState.Setters> <Setter Property="IsEnabled" Value="False" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Button>

When the user enters “Xamarin” in the Entry, the second DataChangedBehavior is executed. This behaviour listens for the bound data to meet a specified condition, in this case that the bound data is equal to “Xamarin”, and executes the GoToStateAction instances in response. These transition the TargetObjects (helpLabel and submitButton) to the StateName (Valid), which causes the Label to disappear (its TextColor is set to Transparent) and the Button to be enabled.

Similarly, the first DataChangedBehavior is executed when the bound data (the Text property of the Entry) is not equal to “Xamarin”. Therefore, if the user deletes “Xamarin” (after entering it) the Invalid states of helpLabel and submitButton are transitioned to, which causes the Label to appear and the Button to be disabled. Note that this is a contrived example, and it would be unperformant to repeatedly transition to a VisualState on every key press in an input control.

Summary

The GoToStateAction class represents an action that will transition a VisualElement to a specified VisualState when triggered. It turns the specified TargetObject to the VisualState of StateName when triggered. The advantage of using the GoToStateAction class is that visual states can be transitioned to from XAML, without requiring use of the VisualStateManager class from code-behind.

The sample application that this code comes from can be downloaded from GitHub, and the Behaviors library can be found on NuGet.

For more information about visual states, see The Xamarin.Forms Visual State Manager.

No comments:

Post a comment