Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change VisualState based on property value

How to change a VisualState based on a property value on WP7?

Im trying to use MVVM pattern and when my model is loading I want my view to go to especific VisualState.

In Silverlight we have triggers for property changes but in WP7 not!

PS: I dont want to use frameworks I want to understand how it is done in WP7.

like image 831
Marcelo de Aguiar Avatar asked Jan 21 '23 11:01

Marcelo de Aguiar


1 Answers

I use the following attached behavior:

using System;
using System.Windows;
using System.Windows.Controls;

namespace PixelLab.WP7.Common.Behaviors
{
    /// 
    /// Provides an attached behavior for binding visual states.
    /// 
    public static class VisualStates
    {
        /// 
        /// Identifies the CurrentState attached property.
        /// 
        public static readonly DependencyProperty CurrentStateProperty = DependencyProperty
            .RegisterAttached(
                "CurrentState",
                typeof(string),
                typeof(VisualStates),
                new PropertyMetadata(TransitionToState));

        /// 
        /// Gets the current visual state of the specified object. This is an attached property. 
        /// 
        /// The source object.
        /// The current visual state of the specified object.
        public static string GetCurrentState(DependencyObject obj)
        {
            return (string)obj.GetValue(CurrentStateProperty);
        }

        /// 
        /// Sets the current visual state of the specified object. This is an attached property.
        /// 
        /// The target object.
        /// The new visual state.
        public static void SetCurrentState(DependencyObject obj, string value)
        {
            obj.SetValue(CurrentStateProperty, value);
        }

        static void startOnGuiThread( Action act )
        {
            var disp = Deployment.Current.Dispatcher;
            if( disp.CheckAccess() )
                act();
            else
                disp.BeginInvoke( act );
        }

        private static void TransitionToState( object sender, DependencyPropertyChangedEventArgs args )
        {
            FrameworkElement elt = sender as FrameworkElement;
            if( null == elt )
                throw new ArgumentException( "CurrentState is only supported on the FrameworkElement" );

            string newState = args.NewValue.ToString();
            startOnGuiThread( () => ExtendedVisualStateManager.GoToElementState( elt, newState, true ) );
        }
    }
}

In your view model, expose a property for the current visual state, and then on the visual element that you want to handle the visual state for you use the following to bind the visual state, for example

<phone:PhoneApplicationPage ...
    xmlns:common="clr-namespace:PixelLab.Common;assembly=PixelLab.Common"
    common:VisualStates.CurrentState="{Binding CurrentState}">
like image 148
Derek Lakin Avatar answered Jan 29 '23 06:01

Derek Lakin