VisualState 指定控件处于特定状态时的外观。
例如,按下 Button 时,它的边框颜色可能与正常时的颜色不同。VisualState 类具有更改控件外观的 Storyboard 属性。控件进入 VisualState.Name 属性指定的状态时,Storyboard 开始。控件退出该状态时,Storyboard 停止。
例如CheckBox就有下面几种状态组:
使用 VisualStateManager 通过将 VisualState 对象的名称传递到 GoToState 方法,来进行状态过渡。
深入学习:
谈谈Silverlight 2中的视觉状态管理
http://kb.cnblogs.com/page/42918/
VisualState 类
http://msdn.microsoft.com/zh-cn/library/system.windows.visualstate(VS.95).aspx
简单说一下WP屏幕方向一共主要有3种 竖向Portrait、左横向LandscapeLeft、右横向LandscapeRight,不支持倒置。
屏幕方向和PhoneApplicationPage相关,可以对每一个页面单独设置。
相关的属性和事件有:
SupportedOrientations 获取或设置页面所支持的手机方向,只能横、只能竖、横竖都可以。
Orientation 获取当前页面的方向
OrientationChanged 页面方向改变时触发此事件
因为竖向分辨率为480*800,横向分辨率为800*480,在布局和呈现上有很大的区别:
可以参考一下这篇文章:
http://www.cnblogs.com/mcgrady/archive/2012/02/06/2340598.html
前面说了这么多,现在进入正题,既然VisualState 指定控件处于特定状态时的外观,而PhoneApplicationPage在方向上又有至少2种状态,那么可以使用VisualState 来呈现竖向Portrait和横向Landscape的两种状态。
来演练一个例子: 在竖向的时候显示圆形,在横向的时候显示方形。
先在界面上添加一个圆形和方形,默认方向是竖向,方形不可见,所以的Opacity为0。
<!--ContentPanel - 在此放置附加内容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Rectangle x:Name="rectangle" Fill="#FFF4F4F5" Height="96" Margin="125,146,177,0" Opacity="0" Stroke="Black" VerticalAlignment="Top"/> <Ellipse x:Name="ellipse" Fill="#FFF4F4F5" Height="158" Margin="117,110,138,0" Opacity="1" Stroke="Black" VerticalAlignment="Top"/> </Grid>
我将状态定义到名字LayoutRoot的Grid 上,也就是默认的那个Grid 。
定义VisualStateGroup 为Layout ,再添加2个VisualState 分别叫竖向Portrait和横向Landscape
<Grid x:Name="LayoutRoot" Background="Transparent"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="Layout"> <VisualState x:Name="Portrait"></VisualState> <VisualState x:Name="Landscape"></VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>
在竖向Portrait状态圆形可见,将Opacity设置为1,将方形Opacity设置为0。
<VisualState x:Name="Portrait"> <Storyboard> <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="ellipse" d:IsOptimized="True"/> <DoubleAnimation Duration="1" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/> </Storyboard> </VisualState>
在横向Landscape状态方形可见,将Opacity设置为1,将圆形形Opacity设置为0。
<VisualState x:Name="Landscape"> <Storyboard> <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/> <DoubleAnimation Duration="1" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="ellipse" d:IsOptimized="True"/> </Storyboard> </VisualState>
还可以添加Transitions实现动画过度:
<VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0:0:1" To="Portrait"/> <VisualTransition GeneratedDuration="0:0:1" To="Landscape"/> </VisualStateGroup.Transitions>
完整页面代码如下,当然使用Blend编辑起来更方便:
首先是监听事件OrientationChanged="PhoneApplicationPage_OrientationChanged"。
然后使用 VisualStateManager 通过将 VisualState 对象的名称传递到 GoToState 方法,来进行状态过渡。
代码如下:
private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e) { switch (e.Orientation) { case PageOrientation.Landscape: case PageOrientation.LandscapeLeft: case PageOrientation.LandscapeRight: VisualStateManager.GoToState(this, "Landscape", true); break; default: VisualStateManager.GoToState(this, "Portrait", true); break; } }
使用模拟器旁边的按钮可以很容易的测试效果:
这样利用VisualState就可以实现比较复杂的方向变化的布局、过度动画等。
并且利用Blend4可以使用可视化编辑也很方便。