Изменить VisualState на основе значения свойства - PullRequest
4 голосов
/ 15 февраля 2011

Как изменить VisualState на основе значения свойства в WP7?

Я пытаюсь использовать шаблон MVVM, и когда моя модель загружается, я хочу, чтобы мое представление перешло на конкретное VisualState.

В Silverlight у нас есть триггеры для изменения свойств, но в WP7 нет!

PS: я не хочу использовать фреймворки, я хочу понять, как это делается в WP7.

Ответы [ 2 ]

8 голосов
/ 16 февраля 2011

Я использую следующее прикрепленное поведение:

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 ) );
        }
    }
}

В вашей модели представления предоставьте свойство для текущего визуального состояния, а затем для визуального элемента, который вы хотите обработать визуальное состояние, для которого вы используете следующее для привязки визуального состояния, например

<phone:PhoneApplicationPage ...
    xmlns:common="clr-namespace:PixelLab.Common;assembly=PixelLab.Common"
    common:VisualStates.CurrentState="{Binding CurrentState}">
1 голос
/ 16 февраля 2011

Изначально поведение DataStateBehavior выглядит идеально подходящим, и в этой статье даже специально говорится об использовании его с WP7.

Однако статья Codeplex проектирует статьюссылки больше не имеют поведения, а поведение отсутствует в Expression Blend (по крайней мере, для проектов WP7).

Я был бы склонен предоставить свойство в ViewModel и программно прослушивать изменения в View исоответственно измените визуальное состояние:

В конструкторе вашего представления:

ViewModelLocator.MainViewModelStatic.PropertyChanged += ViewModelPropertyChanged;

Затем создайте обработчик события, который соответственно изменит состояние:

private void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == MainViewModel.SomeProp)
    {
        // Change the state using the VisualStateManager
    }
}

Дамиан

...