根据属性值更改VisualState

4

如何根据属性值在WP7上更改VisualState?

我正在尝试使用MVVM模式,当我的模型正在加载时,我希望我的视图进入特定的VisualState。

在Silverlight中,我们可以使用触发器来检测属性变化,但在WP7中没有这个功能!

注:我不想使用框架,我想了解在WP7中如何实现。


提到的帖子中的问题并不涉及mvvm,而且在更改视觉状态时也没有帮助,或者至少我没有看到联系。 - Marcelo de Aguiar
2个回答

8
我使用以下附加行为:
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}">

每次当我尝试在Windows Phone上使用该解决方案时,都会在页面初始化时出现ArgumentException。我找不到异常的来源 :( - Viacheslav Smityukh

1

最初DataStateBehavior行为看起来是完美的匹配,而且this article甚至专门讨论了如何在WP7中使用它。

然而,文章引用的Codeplex项目不再具有该行为,并且该行为不适用于Expression Blend(至少对于WP7项目)。

我倾向于在ViewModel上公开一个属性,并以编程方式监听View中的更改并相应地更改Visual State:

在您的View的构造函数中:

ViewModelLocator.MainViewModelStatic.PropertyChanged += ViewModelPropertyChanged;

然后创建一个事件处理程序,相应地更改状态:

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

达米安


Derek的回答更好,我已经点赞了 - 我留下我的答案,以防有人搜索WP7&DataStateBehavior - 他们会发现Derek很酷的附加行为。 - Damian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接