如何根据WP7上的属性值更改VisualState?
我试图使用MVVM模式,当我的模型加载时,我希望我的视图转到特定的VisualState。
在Silverlight中,我们有属性更改的触发器,但在WP7中没有!
PS:我不想使用框架,我想了解它是如何在WP7中完成的。
答案 0 :(得分: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}">
答案 1 :(得分: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
}
}
达米安