読者です 読者をやめる 読者になる 読者になる

PathListBox がおもしろいのでアニメーションするようにしてみた

開催中の MIX10 で Silverlight 4 が発表されて嬉々として触ってるわけですが、 PathListBox が面白くって、Day1 のキーノートでチラッとみた、 eBay の回転するメニューに触発されて、 PathListBox も面白かったので選択されたアイテムを移動させるプログラムを試作してみました。

PathListBox の簡単な使い方については以下を参照。
http://electricbeach.org/?p=503

上のブログでアニメーションの付け方も後日解説するよってなってますが、待ってられません。

XAML は以下。

<Grid x:Name="LayoutRoot" Background="White">
  <Ellipse x:Name="ellipse" Stroke="#FF3F8FEB" HorizontalAlignment="Center" 
           VerticalAlignment="Center" Width="201" Height="201"/>
  <Ellipse Stroke="#FF3F8FEB" Height="110" Margin="0,0,0,191" Width="110" 
           StrokeThickness="11"/>
  <ec:PathListBox HorizontalAlignment="Left" VerticalAlignment="Top">
    <ec:PathListBox.LayoutPaths>
      <ec:LayoutPath SourceElement="{Binding ElementName=ellipse}"/>
    </ec:PathListBox.LayoutPaths>
    <i:Interaction.Behaviors>
      <local:PathListMoveBehavior/>
    </i:Interaction.Behaviors>
    <ed:RegularPolygon Height="70" InnerRadius="0.47211" PointCount="5" 
                       Stretch="Fill" Width="70" Fill="Yellow" />
    <ed:RegularPolygon Height="70" InnerRadius="0.47211" PointCount="5" 
                       Stretch="Fill" Width="70" Fill="Orange" />
    <ed:RegularPolygon Height="70" InnerRadius="0.47211" PointCount="5" 
                       Stretch="Fill" Width="70" Fill="Red"/>
    <ed:RegularPolygon Height="70" InnerRadius="0.47211" PointCount="5" 
                       Stretch="Fill" Width="70" Fill="Purple" />
  </ec:PathListBox>
</Grid>

見た目は以下。

で、PathListBox に設定されている PathListMoveBehavior ってのが、今回試作したやつです。アイテムが選択されたら、アニメーション付きで選択されたアイテムが上部に移動します。

public class PathListMoveBehavior : Behavior<PathListBox>
{
  public PathListMoveBehavior()
  {
  }

  protected override void OnAttached()
  {
    this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
    base.OnAttached();
  }

  protected override void OnDetaching()
  {
    this.AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
    base.OnDetaching();
  }

  private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
  {
    if(e.AddedItems == null || e.AddedItems.Count < 1){
      return;
    }
    if(this.AssociatedObject.LayoutPaths.Count < 1){
      return;  
    }
    LayoutPath animationTarget = this.AssociatedObject.LayoutPaths[0];
    double selectedIndex = this.AssociatedObject.SelectedIndex;
    double itemCount = animationTarget.ActualCapacity;
    
    Storyboard storyboard = new Storyboard();
    DoubleAnimation animation = new DoubleAnimation();
    Storyboard.SetTarget(animation,animationTarget);
    Storyboard.SetTargetProperty(animation,new PropertyPath(LayoutPath.StartProperty));
    animation.Duration = new Duration(new TimeSpan(0,0,0,0,500));
    animation.To = 1.0 - ((1.0 / itemCount) * selectedIndex);
    storyboard.Children.Add(animation);
    
    storyboard.Begin();
  }
}

あまり複雑でないので説明は省略。

移動させたい位置とか、移動の方向とか、回転速度は一定にしたいとか、Distribution が even じゃなかったり、Padding が設定されてたりとかだとうまく動かないとかあったりするのですが、まぁ、試作ってことで。