Transition コントロール

Last Updated 2012/02/16


スマートフォンなどが普及したことでフォーム内の内容がアニメーションするユーザーインターフェースが普通になってきました。WPF はそれらを実現できる機能を持っています。このページではフォームのクライアント領域内のコントロールをアニメーションして変更するテクニックについて説明します。


Transition は日本語にしにくい言葉です。直訳すれば、「推移」とか「変遷」あるいは「過渡期」ですが、「遷移」と呼ぶ人もいます。ビットマップ効果のページで紹介しましたが、画像を入れ替えるのも Transition の一種といっていいでしょう。ということで、このページでは Transition とそのまま呼ぶことにします。

さて、ここで取り上げる Transition は、フォームの内容(配置したコントロール)を Transition のテクニックを使って別の内容に入れ替えます。この応用例を挙げるとすると、ウィザードがそうですね。ウィザードとは、複雑な一連の手続きを分かりやすくするため、一問一答形式で設定していくもので、フォームの内容だけを入れ替えるような手法をさします。

Transition をどのように実行するか(要するに、アニメーションの方法)は好みの問題ですが、実用的という意味でスライドイン・スライドアウトとフェードイン・フェードアウトの二種類を扱うことにします。

Transition するフォームの内容は UserControl として作成します。こうすることでフォームのデザインと同じ手順で作成することができるメリットがあります。つまり、複数の UserControl を用意しておいて、アニメーションして入れ替えます。

愛想のない画面ですが、下図の赤色と緑色の部分は UserControl で、フェードイン・フェードアウトして入れ替えたところです。以下、便宜上、Transition の対象となる UserControl をページと呼ぶことにします。

WpfTransition1 WpfTransition2

Transition を担当するコントロールは各ページのコンテナコントロールにすぎません。以下は、フェードイン・フェードアウトの Transition 機能を持つコントロールですが、これだけです。

(WpfFadeTransition.xaml)
<UserControl x:Class="emanual.Wpf.Controls.WpfFadeTransition"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Loaded="control_Loaded">

  <Grid>
    <ContentControl Name="PART_ContentPresenter" />
  </Grid>
</UserControl>

Transition コントロールの動作は分離コードで定義します。ポイントは、フェードイン・フェードアウトするアニメーションを定義する部分で、この部分を別のものに変更するだけでいろいろな Transition に対応することができます。

(WpfFadeTransition.xaml.cs)
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace emanual.Wpf.Controls
{
  public partial class WpfFadeTransition : UserControl
  {
    private int FCurrentPage = 0;
    private List<UserControl> FPageList = new List<UserControl>();
    private Storyboard FFadeInAnimation;
    private Storyboard FFadeOutAnimation;

    //---------------------------------------------------------------------------------------------
    public WpfFadeTransition()
    {
      InitializeComponent();
    }

    //---------------------------------------------------------------------------------------------
    private void control_Loaded(object sender, RoutedEventArgs e)
    {
      // フェードインするアニメーション
      FFadeInAnimation = new Storyboard();
      var fadeInAnimation = new DoubleAnimation();
      fadeInAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 250));
      fadeInAnimation.From = 0.0;
      fadeInAnimation.To = 1.0;
      fadeInAnimation.DecelerationRatio = 0.8;
      Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath("Opacity"));
      FFadeInAnimation.Children.Add(fadeInAnimation);

      // フェードアウトするアニメーション
      FFadeOutAnimation = new Storyboard();
      var fadeOutAnimation = new DoubleAnimation();
      fadeOutAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 500));
      fadeOutAnimation.From = 1.0;
      fadeOutAnimation.To = 0.0;
      fadeInAnimation.DecelerationRatio = 0.8;
      Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath("Opacity"));
      FFadeOutAnimation.Children.Add(fadeOutAnimation);

      // 最初のページを表示する
      this.ShowPage(0);
    }

    //---------------------------------------------------------------------------------------------
    // 指定の UserControl を追加する
    public void AddPage(UserControl page)
    {
      FPageList.Add(page);
    }

    //---------------------------------------------------------------------------------------------
    // 指定のページ番号のページを表示する
    // page : ページ番号
    public void ShowPage(int page)
    {
      if (FPageList.Count < 1)
        return;

      if (PART_ContentPresenter.Content == null)
      {
        UserControl fadeInPage = FPageList[page];
        fadeInPage.Loaded += fadeIn_Loaded;
        PART_ContentPresenter.Content = fadeInPage;
      }
      else
      {
        UserControl fadeOutPage = PART_ContentPresenter.Content as UserControl;

        if (fadeOutPage != null)
        {
          fadeOutPage.Loaded -= fadeIn_Loaded;
          this.UnloadPage(fadeOutPage);
          FCurrentPage = page;
        }
      }
    }

    //---------------------------------------------------------------------------------------------
    private void UnloadPage(UserControl page)
    {
      if (FPageList.Count < 1)
        return;

      FFadeOutAnimation.Completed += fadeOut_Completed;
      FFadeOutAnimation.Begin(PART_ContentPresenter);
    }

    //---------------------------------------------------------------------------------------------
    private void fadeIn_Loaded(object sender, RoutedEventArgs e)
    {
      FFadeInAnimation.Begin(PART_ContentPresenter);
    }

    //---------------------------------------------------------------------------------------------
    private void fadeOut_Completed(object sender, EventArgs e)
    {
      PART_ContentPresenter.Content = null;
      this.ShowPage(FCurrentPage);
    }

    //---------------------------------------------------------------------------------------------
  } // end of WpfFadeTransition class
} // end of namespace

次の ZIP ファイルはフェードイン・フェードアウトおよびスライドイン・スライドアウトに対応する Transition コントロールとテスト用アプリケーションの Visual Studio 2010 のプロジェクトを含みます。フリ−ウエアですからどなたでも自由にご利用できます。

WpfTransition.zip (72,361 bytes)

−以上−