VisualStateManager In Xamarin.Forms – Phase 1

VisualStateManager is a new upcoming feature in Xamarin.Forms, that allows you to attach additional state to a VisualElement, without sub classing the VisualElement. Rather than having to base things off IsEnabled, you could create your own states, such as Normal, Disabled and Focussed.

Note: This isn’t even merged into the Xamarin.Forms master branch yet. I am basing this off PR 1405.

 

VisualStateGroups

VisualStateGroups hold a list of Visual States that the element can be in, and we can set this to the VisualStateManager.VisualStateGroups attached property of an Entry.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App.MainPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="Entry" x:Key="StyledEntry">
                <Setter Property="VisualStateManager.VisualStateGroups">
                    <VisualStateGroupList x:Name="CommonStates">
                        <VisualStateGroup>
                            <VisualState x:Name="Normal">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="White"></Setter>
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Invalid">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="Red"></Setter>
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateGroupList>
                </Setter>
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <Image Source="icon.png" />
            <Entry Text="I turn red when i'm invalid" 
                   VerticalOptions="Center" 
                   HorizontalOptions="Center" x:Name="WelcomeEntry" Style="{StaticResource StyledEntry}" />
    </StackLayout>
</ContentPage>

When it’s Invalid, it has a background of red, when it’s Normal, it has a background of white.

Then in code behind, you can change the state.

VisualStateManager.GoToState(WelcomeEntry, "Invalid");

State Management

What’s the point of this. Well in it’s current phase, there is none that I can see. Having to use code behind to manage the states is an immediate write off for me. And there are much easier ways to manage states via Style Triggers, reading off a ViewModel state, as I go through in my State Management video, in my Application Architecture Course.

Triggers

I am hoping this might be included in an upcoming phase, but I also briefly hacked on a CurrentState property into the VisualStateManager, to be able to do some changes of state via Triggers.

public static readonly BindableProperty CurrentStateProperty =
	BindableProperty.CreateAttached("CurrentState", typeof(string), typeof(VisualElement),
	defaultValue: "", propertyChanged: CurrentStatePropertyChanged);

static void CurrentStatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
	if (!string.IsNullOrEmpty(Convert.ToString(newValue)))
		GoToState((VisualElement)bindable, (string)newValue);
}

Then in my code I added this Style Trigger.

<Style TargetType="Entry" x:Key="StyledEntry">
    <Style.Triggers>
        <Trigger TargetType="Entry"
                 Property="IsFocused" 
                 Value="True">
            <Setter Property="VisualStateManager.CurrentState" Value="Invalid" />
        </Trigger>
</Style.Triggers>

The result, is when the entry IsFocussed, it changes state, and hence properties.

Summary

I see some good potential for this feature, even though it’s in a early stage. Hopefully with the addition of Triggers, directly in the VisualState themselves, rather than a property I just hacked on, could allow this feature to really help separate state management in the view, all in XAML, from the ViewModel.


Posted

in

by

Tags: