Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[WPF/xaml]Storyboardでアニメーションをつくる2(TargetPropertyの階層的な指定)

More than 1 year has passed since last update.

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

Storyboard関連
- [WPF/xaml] xaml+C#で当番決めのためのルーレットを作る
- [WPF/xaml]Storyboardでアニメーションをつくる
- [WPF/xaml]Storyboardでアニメーションをつくる2(TargetPropertyの階層的な指定)

やりたいこと

以前、Storyboardでアニメーションをつくる方法を勉強したが、その中の「DoubleAnimationUsingKeyFrames」でTargetPropertyを指定している部分の、

a.xaml
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"  Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)">

の「(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)」の部分が、どういうことを書いているのか実はよくわかってなかった。
この際はっきりさせたい。

以前のコードはこちら参照
https://qiita.com/tera1707/items/a7fcdd95fc3120ae3c8b

調べた時に見たサイト

こちらに、知りたいことはすべて書いてあった。

アニメーション(WPF)(++C++)
https://ufcpp.net/study/dotnet/wpf_xamlani.html
>「TergetProperty を階層的に指定」
>「TergetProperty で配列的にアクセス」

書いてあったが、見るだけでは勉強にならないので、自分なりの理解を書いてみようと思う。

自分なりの理解

別の書き方

Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)"

Storyboard.TargetProperty="RenderTransform.Children[0].X"
は、同じことを表している。

②を省略せずに正しく書くと、①の書き方になる。

②の意味合い

②は、日本語でいうと、下記のようなことを表している。

  • 対象(ここではRectangle(名前はslider))に含まれている、
  • RenderTransformにセットされているもの(Childrenの0番目)の、
  • Xをターゲットプロパティにする。

②で省略していること

②の書き方では。いろいろと省略されていることがある。

  • RenderTransformは正しく言うと、UIElementクラスで定義されているメンバRenderTransformである。
  • Childrenは正しく言うと、TransformGroupクラスで定義されているメンバChildrenである。
  • Xは正しく言うと、TranslateTransformクラスで定義されているメンバXである。

①の意味合い

で、書き方としては、省略しているものを省略無しで正しく書こうとするとカッコ()を付けるようなので、

  • RenderTransform → (UIElement.RenderTransform)
  • Children     → (TransformGroup.Children)
  • X         → (TranslateTransform.X)

となり、それぞれをつなげると、つまり①の内容になる。

前提

①または②のように書くと、Storyboardは動いてくれるのだが、前提として対象のRectangle(名前はslider)のRenderTransformに、
image.png
「TranslateTransform」をセットした「TransformGroup」がセットされてないと、例外で動かなかった。これは、"RenderTransform.Children[0].X"の中の右半分、「.Children[0].X」が存在しなかったからと思われる。

自分で意図してセットしないと、RectangleのRenderTransformにはなにも入っていないので、Storyboardでターゲットプロパティとして指定するためには、「Storyboard動作時に」TranslateTransformが入ったTransformGroupがセットされていることが前提となる。
(セットしてなくても、アプリ起動時には落ちない。Storyboard動作時に落ちる。)

(UIElement.RenderTransform)の「UIElement」はどこから来た?

今回のstoryboardのターゲットはRectangleで、そのRectangleは「UIElement」を継承してできている。

Rectangle Class
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.shapes.rectangle?view=netframework-4.8
image.png

UIElementクラスで「RenderTransform」は定義されいているので、「(UIElement.RenderTransform)」と書く。

※ためしに、(UIElement.RenderTransform)のところを(FrameworkElement.RenderTransform)とか(Shape.RenderTransform)とか書いても動くのは動く。

自分なりの結論

a.xaml
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"  Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)">

上記のStoryboard.TargetPropertyの書き方は、省略をせずに、階層的にプロパティを書いたものだった。

別の例

別の例として、背景の色を時間を追って変化させたいときに、下記のようにColorAnimationUsingKeyFrames を書いたとする。

a.xaml
<ColorAnimationUsingKeyFrames  BeginTime="00:00:00"  Storyboard.TargetName="BackgroundBorder" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)">

この中のStoryboard.TargetPropertyは、

  • 対象に含まれている、
  • Backgroundにセットされているもの(SolidColorBrush)の、
  • Colorをターゲットプロパティにする。

ということ。省略して書くと、

a.xaml
<ColorAnimationUsingKeyFrames  BeginTime="00:00:00"  Storyboard.TargetName="BackgroundBorder" Storyboard.TargetProperty="Background.Color">

となる。またこの場合も、対象(ここではBackgroundBorderという名前のBorder)のBackgroundがあらかじめ設定されていないと例外で落ちる。

この書き方をAttributeSyntaxというらしい.xaml
<!-- ここで、Background="Gray"がないとStoryboard実行時に落ちる -->
<Border Name="BackgroundBorder" CornerRadius="2" Height="28" Width="60" BorderBrush="White" BorderThickness="2" Background="Gray"/>

Background="Gray"は、Border のBackgroundに、グレー色のSolidColorBrushがセットされている、ということを示す。
(xamlが勝手にそういうことをしてくれている)

それがないと落ちてしまうのは、Storyboardが変化させようとするColorを持っているSolidColorBrushが存在しないからだと思われる。

Background="Gray"は、Border のBackgroundに、グレー色のSolidColorBrushがセットされている」というのは、個人的には下記のように書くとイメージが湧きやすかった。

この書き方を「PropertyElementSyntax」というらしい.xaml
<Border Name="BackgroundBorder" CornerRadius="2" Height="28" Width="60" BorderBrush="White" BorderThickness="2">
    <Border.Background>
        <SolidColorBrush Color="Gray"/>   <!-- ←これがないと、storyboardが設定するものがなくて落ちてしまう。 -->
    </Border.Background>
</Border>

参照

アニメーション(WPF)(++C++)
https://ufcpp.net/study/dotnet/wpf_xamlani.html
>「TergetProperty を階層的に指定」
>「TergetProperty で配列的にアクセス」

XAML の基本構造(WPF)
Attribute SyntaxとかProperty Element Syntaxとか
https://ufcpp.net/study/dotnet/wpf_xamlbasic.html?key=attribute#attribute
>「プロパティの設定」

tera1707
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away