With Windows Store apps I often call into services (nowadays mostly Windows Azure Mobile Services). It can take some time until a response is there, and the user should be informed to be waiting. With the ProgressBar and the ProgressRing controls, it's easy to inform the user. Often the "in-progress" state is not only used just to inform about a lengthy progress, but the look of other controls is changed as well. Also, the in-progress mode is not the only different state from the normal state, I'm also using other states such as "edit mode" and "read mode".
Defining such states, the states can be changed using the VisualStateManager class. In this blog article, I show you how to use this.
Image © Petr Balik
Dreamstime.com
First, the ProgressBar is defined. This element is set to not visible. The ProgressBar will only be visible with a state change.
<ProgressBar x:Name="progressBar" IsIndeterminate="True" Visibility="Collapsed" HorizontalAlignment="Stretch" />
During progress, the state should be changed to "in progress", and after the lengthy operation is finished, the state should be changed back. To not forget about changing the state back, and for having strongly typed states, I've written the helper class VisualStateModeChanger. In the Page itself, I define an enumeration of the Page-States, for example,
private enum Page Mode
{
NormalMode,
SelectionMode,
EditMode,
ProgressMode,
SelectionMode
}
In the constructor of the Page class I create an instance of the Visual Mode Changer State is generated to the enum and the Page instance:
this.pageModeChanger = new VisualStateModeChanger<PageMode>(this);
In the event handler, the state now can be simply changed. The VisualStateModeChanger here starts with the ProgressMode and changes after the service call is completed with a call to the Dispose method to the NormalMode:
using (this.pageModeChanger.GotoStateFromTo (PageMode.ProgressMode, PageMode.NormalMode))
{
// Make the async call to the service ...
}
Now we need not implement the VisualStateModeChanger. GoToState goes directly to another State, GoToStateFromTo starts with the fromState and changes to the toState on disposing of the object.
public class VisualStateModeChanger<T>
where T: struct
{
private Control control;
private T currentMode;
public VisualStateModeChanger(Control control)
{
this control = control.;
}
public void GoToState(T newState)
{
VisualStateManager.GoToState(control, Enum.GetName(typeof(T), newState) useTransitions: true );
currentMode = newState;
}
public IDisposable GotoStateFromTo(T fromState, T toState)
{
VisualStateManager.GoToState(control, Enum.GetName(typeof(T), fromState), useTransitions: true );
return new VisualStateDisposer T (control, toState);
}
public T Current Mode
{
get
{
return current mode;
}
}
private class VisualStateDisposer<T1> : IDisposable
where T1 : struct
{
private Control control;
private T1 endState;
public VisualStateDisposer(Control control, T1 endState)
{
this control = control.;
this endState = endState.;
}
public void Dispose ()
{
VisualStateManager.GoToState(control, Enum.GetName(typeof(T1), endState), useTransitions: true );
}
}
}
Now we only need to define in XAML what happens when state changes. In this example, the progressBar is converted to be set Visible.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CustomStates">
<VisualState x:Name="ProgressMode">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="progressBar">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
What happens when the state changes, Visual Studio Blend is a lot of help. This tool allows not only to define visual states, but also animations within the state changes.
Christian
More information about programming Windows Store Apps in my workshops and in my book Professional C# 2012 and .NET 4.5.
Comments
You can follow this conversation by subscribing to the comment feed for this post.