TabControlのタブから選択された画像を、アニメーションで表示する
今回は、2つのサンプルを紹介します。1つは、XMLファイルからTabControlのタブに表示する文字列を読み取って表示し、選択されたタブに該当する画像とコメントをアニメーションで表示するものです。もう1つは、RichTextBox内に入力した文字のサイズや色を変化させ、任意の位置に画像をレイアウトするものです。
まずは、TabControlのサンプルの紹介です。実装する機能の動作は次の通りです。
TabControlのタブに表示されているタイトル名をクリックすると、画像がアニメーションを伴って切り替わります(図1)。

|
図1: タブをクリックして画像がアニメーションを伴って切り替わっている |
サンプル・ファイルはこちらからダウンロードできます。
VS 2010のデザイン画面上で、コントロールをレイアウトする
これまでのサンプル作成時と同様の手順で、新規Silverlight 4プロジェクト(プロジェクト名は「SL4_TabControl」)を作成してください。プロジェクトの依存関係も設定してください。
次に、画像のファイル名を記録したXMLファイル(リスト1)を追加します。XMLデータはLINQ to XMLで処理するため、「プロジェクト(P) > 参照の追加(F)」からSystem.Xml.Linqを追加しておきます。
ソリューションエクスプローラ内にImageというフォルダを作成して、画像も追加しておきます。
ダウンロードされたサンプル・ファイルにはXMLファイルと画像は追加済みです。
リスト1: XML文書ファイル(photo_etc.xml)
01 | <!--//--><![CDATA[// ><!-- |
08 | 抜けるような青空に,銀杏の木が突き刺さっている。 |
UserControlのプロパティ内の[レイアウト]を展開して、Widthに800、Heightに600を指定します。
次にツールボックスからTextBlock、「すべてのSilverlightコントロール」からTabControlをレイアウトします(図2)。ツールボックスにTabControlコントロールが登録されていない場合は、「これからはじめるSilverlight 4」の第2回を参考に登録してください。

|
図2: TextBlock、TabControlをレイアウトした |
書き出されるXAMLコードは省略します。
ロジックコードを記述する
ソリューションエクスプローラ内のMainPage.xamlを展開し、MainPage.xaml.vbをダブルクリックしてコード画面を開きます。
リスト2のようにロジックコードを記述します。
リスト2: ロジックコード(MainPage.xaml.vb)
1 | <!--//--><![CDATA[// ><!-- |
LINQ to XMLでXMLを処理するクラスの含まれる、System.Xml.Linq名前空間をインポートします。ImageのSourceプロパティに画像を指定するクラスの含まれる、System.Windows.Media.Imaging名前空間をインポートします。DropShadowEffectの影を付けるのに必要なクラスの含まれる、System.Windows.Media.Effects名前空間をインポートします。
1 | <!--//--><![CDATA[// ><!-- |
4 | Imports System.Windows.Media.Imaging |
5 | Imports System.Windows.Media.Effects |
StackPanelの新しいリストとして作成するmyStackPanelArrayをメンバ変数として宣言します。
1 | <!--//--><![CDATA[// ><!-- |
3 | Dim myStackArray As New List(Of StackPanel) |
■ページが読み込まれた時の処理
XElement.LoadメソッドでXML文書ファイル(photo_etc.xml)を読み込みます。読み込んだXML文書から要素のコレクションを取得するクエリ(query)を定義します。queryを実行します。クエリコレクション内を変数resultで反復処理しながら以下の処理を実行します。
要素の値を取得し、画像名についている「.jpg」の拡張子を外したものを変数titleImageに格納しておきます。新しいStackPanelのインスタンスmyStackPanelオブジェクトを生成します。また、新しいTabItemのインスタンスmyTabItemオブジェクトを生成します。TabItemオブジェクトのHeaderプロパティに、titleImage変数を指定します。TabControlのタブに画像のタイトルが表示されます。StackPanelオブジェクトのOrientationプロパティにVerticalを指定し、子要素のスタックされる向きを垂直方向とします。画像の下に説明文が表示される形となります。
新しいDropShadowEffectのインスタンスdrEffectオブジェクトを生成します。プロパティであるOpacityに0.6、ShadowDepthに8を指定します。透過度が80%で、画像と画像の影との間の距離が8である影が表示されます。
新しいImageのインスタンスmyImageオブジェクトを生成します。Width、Heightプロパティを指定し、Marginプロパティで余白に10を指定します。Sourceプロパティには、画像を保管しているImageフォルダと要素の値を保持しているimageName変数を連結して、相対Uriで指定します。Effectプロパティに先に設定したdrEffectオブジェクトを指定します。
新しいTextBlockのインスタンスmyTextBlockオブジェクトを生成します。Widthプロパティを指定し、Textプロパティに要素の値を指定します。
myStackPanelオブジェクトにAddメソッドで画像を追加し、同じく説明を追加します。StackPanelの新しいリストとして作成しておいた、myStackArrayオブジェクトにAddメソッドで、画像と説明の追加されたmyStackPanelオブジェクトを追加します。myTabItemオブジェクトのContentプロパティにmyStackPanelオブジェクトを指定し、TabControlにAddメソッドで、myTabItemオブジェクトを指定します。TabControlの中に、タブによって切り替わる、画像とその説明文が配置されることになります。
01 | <!--//--><![CDATA[// ><!-- |
03 | Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded |
04 | Dim xmldoc As XElement = XElement.Load("photo_etc.xml") |
05 | Dim query = From c In xmldoc.Descendants("情報") Select c |
06 | For Each result In query |
07 | Dim imageName As String = result.Element("画像名").Value |
08 | Dim titleImageLen As Integer = Len(imageName) - 4 |
09 | Dim titleImage As String = Left(imageName, titleImageLen) |
11 | Dim myStackPanel As New StackPanel |
12 | Dim myTabItem As New TabItem |
13 | myTabItem.Header = titleImage |
15 | myStackPanel.Orientation = Orientation.Vertical |
17 | Dim drEffect As New DropShadowEffect |
23 | Dim myImage As New Image |
27 | .Margin = New Thickness(10) |
28 | .Source = New BitmapImage(New Uri("Image/" & imageName, UriKind.Relative)) |
32 | Dim myTextBlock As New TextBlock |
33 | myTextBlock.Width = 320 |
34 | myTextBlock.Text = result.Element("説明").Value |
36 | myStackPanel.Children.Add(myImage) |
37 | myStackPanel.Children.Add(myTextBlock) |
39 | myStackArray.Add(myStackPanel) |
40 | myTabItem.Content = myStackPanel |
41 | TabControl1.Items.Add(myTabItem) |
■TabControlのタブが切り替えられた時の処理
1 | <!--//--><![CDATA[// ><!-- |
3 | Private Sub TabControl1_SelectionChanged(ByVal sender As Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles TabControl1.SelectionChanged |
※画像と説明文のテキストが回転する処理
新しいStoryBoardとDoubleAnimation(myStoryBoardとmyDoubleAnimation)のインスタンスを生成します。2秒かけて0°~360°まで回転させるため、DoubleAnimationのFromに0を指定し、Toには360を指定し、Durationには2秒を指定します。
新しいRotateTransformのインスタンスを生成します。RotateTransformは、指定された点を中心としてオブジェクトを時計回りに回転させるクラスです。CenterXとCenterYに、画像の中心点の座標値を指定します。
TablControlの選択されたタブのインデックス(SelectedIndex)に該当する、myStackArrayオブジェクトのRenderTransformプロパティに、myRotateTransformオブジェクトを指定します。RenderTransFormプロパティでは、UIElement の描画位置に関係する変換情報を設定することができます。myStackArrayオブジェクトにRenderTransformプロパティが設定されていない場合は、新しいRotateTransformオブジェクトのインスタンスを生成し、myStackArrayオブジェクトのRenderTransformプロパティにmyRotateTransformオブジェクトを指定します。
SetTargetメソッドでタイムラインにDoubleAnimationのインスタンスであるmyDoubleAimationを指定し、タイムラインの対象となるオブジェクトにRotateTransformのインスタンスであるmyRotateTransformを指定します。
また、SetTargetPropertyメソッドで、タイムラインにDoubleAnimationのインスタンスであるmyDoubleAimationを指定し、アニメーション化するプロパティにNew PropertyPath("(RotateTransform.Angle)")と指定し、Angleプロパティを指定して回転させます。
StoryBoardのインスタンスmyStoryBoardにAddメソッドでmyDoubleAnimationを追加します。BeginメソッドでStoryBoardを実行します。これで、画像とテキストの追加されたmyStackArrayオブジェクトが回転します。
01 | <!--//--><![CDATA[// ><!-- |
03 | Dim myStoryBoard As New Storyboard |
04 | Dim myDoubleAnimation As New DoubleAnimation |
05 | With myDoubleAnimation |
08 | .Duration = New Duration(TimeSpan.FromSeconds(2)) |
10 | Dim myRotateTransform As New RotateTransform |
11 | With myRotateTransform |
16 | myStackArray(TabControl1.SelectedIndex).RenderTransform = myRotateTransform |
17 | If myStackArray(TabControl1.SelectedIndex).RenderTransform Is Nothing Then |
18 | myRotateTransform = New RotateTransform |
19 | myStackArray(TabControl1.SelectedIndex).RenderTransform = myRotateTransform |
22 | Storyboard.SetTarget(myDoubleAnimation, myRotateTransform) |
23 | Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath("(RotateTransform.Angle)")) |
24 | myStoryBoard.Children.Add(myDoubleAnimation) |
※画像が近づいてくるアニメーション
新しいStoryBoardとDoubleAnimationのインスタンス(myStoryBoard2とmyDoubleAnimation2)を生成します。
2秒をかけて、オブジェクトをZ軸に沿って、-2000~0まで移動させるため、DoubleAnimationのFromに-2000を、Toには0を、Durationには2秒を指定します。
新しいPlaneProjectionのインスタンスを生成します。PlaneProjectionは、オブジェクトに対する遠近法変換を表わすクラスです。TablControlの選択されたタブのインデックス(SelectedIndex)に該当する、myStackArrayオブジェクトのProjectionプロパティに、myPlaneProjectionオブジェクトを指定します。Projectionプロパティは、UIElement のレンダリング時に射影を設定できるプロパティです。
myStackArrayオブジェクトにProjectionプロパティが設定されていない場合は、新しいPlaneProjectionオブジェクトのインスタンスを生成し、myStackArrayオブジェクトのProjectionプロパティにmyPlaneProjectionオブジェクトを指定します。
SetTargetメソッドで、タイムラインにDoubleAnimationのインスタンスであるmyDoubleAimation2を指定し、タイムラインの対象となるオブジェクトにPlaneProjectionのインスタンスであるmyPlaneProjectionを指定します。SetTargetPropertyメソッドで、タイムラインにDoubleAnimationのインスタンスであるmyDoubleAimation2を指定し、アニメーション化するプロパティにNew PropertyPath("(PlaneProjection.LocalOffsetZ)")と指定します。
StoryBoardのインスタンスmyStoryBoard2にAddメソッドでmyDoubleAnimation2を追加します。BeginメソッドでStoryBoardを実行します。これで、画像とテキストの追加されたmyStackArrayオブジェクトが近づくように表示されます。
01 | <!--//--><![CDATA[// ><!-- |
03 | Dim myStoryBoard2 As New Storyboard |
04 | Dim myDoubleAnimation2 As New DoubleAnimation |
05 | With myDoubleAnimation2 |
08 | .Duration = New Duration(TimeSpan.FromSeconds(2)) |
10 | Dim myPlaneProjection As New PlaneProjection |
12 | myStackArray(TabControl1.SelectedIndex).Projection = myPlaneProjection |
13 | If myStackArray(TabControl1.SelectedIndex).Projection Is Nothing Then |
14 | myPlaneProjection = New PlaneProjection |
15 | myStackArray(TabControl1.SelectedIndex).Projection = myPlaneProjection |
17 | Storyboard.SetTarget(myDoubleAnimation2, myPlaneProjection) |
18 | Storyboard.SetTargetProperty(myDoubleAnimation2, New PropertyPath("(PlaneProjection.LocalOffsetZ)")) |
19 | myStoryBoard2.Children.Add(myDoubleAnimation2) |