65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight 可视状态示例

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (8投票s)

2009年4月8日

CPOL

3分钟阅读

viewsIcon

32902

downloadIcon

354

Silverlight 视觉状态及其如何在控件中使用的一个有趣的方面。

引言

在本文中,我想说明 Silverlight 视觉状态及其如何在控件中使用的一个有趣的方面。 您可以在我的博客上阅读:Cellbi 博客

Silverlight 控件的关键功能之一是能够为控件声明不同的状态并指定它们之间的转换,这已不是什么秘密。

状态之间的每次转换都需要时间进行动画处理,而且通常需要知道转换何时真正完成。 假设我们花了几个小时在 Blend 中准备了一个简单的按钮。 类似于下面的图片 ;-)

StateEventsExSource

上面的按钮由三个部分组成:LayoutRoot(一个网格,其宽度和高度绑定到控件的“Width”和“Height”属性),Host(一个按钮背景,其颜色属性绑定到控件的“Background”属性)和 Content(一个绿色箭头)。

XAML 中的视觉状态

这是在 xaml 代码中所做的努力的结果,它为按钮指定了简单的样式。

<vsm:VisualStateManager.VisualStateGroups>
  <vsm:VisualStateGroup x:Name="CommonStates">
    <vsm:VisualStateGroup.Transitions>
      <vsm:VisualTransition GeneratedDuration="00:00:00.4000000" To="MouseOver"/>
      <vsm:VisualTransition GeneratedDuration="00:00:00.4000000" To="Play"/>
      <vsm:VisualTransition GeneratedDuration="00:00:00.4000000"/>
    </vsm:VisualStateGroup.Transitions>

    <vsm:VisualState x:Name="Normal">
      <Storyboard/>
    </vsm:VisualState>
    <vsm:VisualState x:Name="MouseOver">
      <Storyboard>
        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
            Duration="00:00:00.4000000"
            Storyboard.TargetName="Host"
            Storyboard.TargetProperty="(UIElement.Opacity)">
          <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
      </Storyboard>
    </vsm:VisualState>
    <vsm:VisualState x:Name="Play">
      <Storyboard>
        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
            Duration="00:00:00.4000000"
            Storyboard.TargetName="Host"
            Storyboard.TargetProperty="(UIElement.Opacity)">
          <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
      </Storyboard>
    </vsm:VisualState>
  </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>

现在,我们需要向此按钮添加行为逻辑。 它应该有两种方法:StartStop。 当鼠标移动到按钮上方时,主机应更改其不透明度。 当调用 Stop 方法或只是单击该按钮时,内容应开始旋转 - 按钮的播放状态。

从 C# 代码中使用视觉状态

从实现的角度来看,这可以通过以下方式完成。 从图片中可以看出,该按钮具有三种状态:“Normal”、“MouseOver”和“Play”。 当鼠标指针移动到控件上方时,我们应该开始过渡到 MouseOver 状态,当单击该按钮时,我们应该开始过渡到 Play 状态,并且**只有在那之后**,我们才开始内容的旋转。

请注意:“只有在那之后”才开始内容的旋转 ;) 问题是状态之间的转换可能需要时间。 并且,如果您在单击按钮后立即开始内容的旋转 - 它将与转换以并行模式发生,并且相信我,它看起来会非常难看。 因此,为了避免这种情况,我们绝对应该在转换完成后开始旋转。

Silverlight 提供了一种简单的方法来准确地执行此操作。 我们可以使用视觉状态管理器和视觉状态。 XAML 代码包含一个 VisualStateManager,它声明 VisualStates 和 Transitions。 因此,为了实现我们的任务,我们只需要在 OnApplyTemplate 方法覆盖中访问 VisualStateGroups 并处理几个事件。 让我们看一下代码的样子

public override void OnApplyTemplate()
{
  base.OnApplyTemplate();

  FrameworkElement root = 
    GetTemplateChild("LayoutRoot") as FrameworkElement;

  .........

  commonStatesGroup = GetVisualStateGroup(root, "CommonStates");
  HookVisualStateGroupEvents(commonStatesGroup);
}

VisualStateGroup GetVisualStateGroup(FrameworkElement root, string groupName)
{
  if (root == null)
    return null;

  IList groups = VisualStateManager.GetVisualStateGroups(root);
  if (groups == null)
    return null;

  foreach (VisualStateGroup gr in groups)
    if (gr != null && gr.Name == groupName)
      return gr;

  return null;
}

void HookVisualStateGroupEvents(VisualStateGroup group)
{
  if (group == null)
    return;
  group.CurrentStateChanged += group_CurrentStateChanged;
}

void group_CurrentStateChanged(object sender, 
           VisualStateChangedEventArgs e)
{
  if (e.NewState != null && 
      e.NewState.Name == "Play")
    OnStarted();
}

现在,让我们看看上面的代码中做了什么。 首先,我们在 OnApplyTemplate 方法中访问“CommonStates”视觉组,然后简单地订阅 CurrentStateChanged 事件。 处理程序中的 VisualStateChangedEventArgs 仅为我们提供了三个属性:ControlOldStateNewState。 但是,这正是我们在该处理程序中需要的。 ;-) 当我们的事件处理程序被调用时,我们可以说该控件已进行动画处理,并且我们知道为哪些状态完成了动画处理。 从这一点开始,我们知道控件的状态已更改,我们可以开始内容旋转。

希望这个示例对您有所帮助。

Silverlight 视觉状态示例 - CodeProject - 代码之家
© . All rights reserved.