【WPF/XAML】Visibility変更時のアニメーション切替

公開日: : 最終更新日:2015/10/20 Blog, Microsoft , ,

ストーリーボードを使わずに、Visibility変更でアニメーションを発生させたかった。
やってる人を発見。感謝(Ms-PLライセンス)

WPF: How To Animate Visibility Property?

Imports System.Windows.Media.Animation

Public Class VisibilityAnimation

    Public Enum AnimationType
        None
        Fade
    End Enum

    Private Const AnimationDuration As Integer = 300
    Private Shared ReadOnly _hookedElements As Dictionary(Of FrameworkElement, Boolean) = _
        New Dictionary(Of FrameworkElement, Boolean)()

    Public Shared Function GetAnimationType(obj As DependencyObject) As AnimationType
        Return DirectCast(obj.GetValue(AnimationTypeProperty), AnimationType)
    End Function

    Public Shared Sub SetAnimationType(obj As DependencyObject, value As AnimationType)
        obj.SetValue(AnimationTypeProperty, value)
    End Sub

    Public Shared ReadOnly AnimationTypeProperty As DependencyProperty = _
        DependencyProperty.RegisterAttached("AnimationType", _
                                            GetType(AnimationType), _
                                            GetType(VisibilityAnimation), _
                                            New FrameworkPropertyMetadata(AnimationType.None, _
                                                                          New PropertyChangedCallback(AddressOf OnAnimationTypePropertyChanged))
                                            )

    Private Shared Sub OnAnimationTypePropertyChanged(dependencyObject As DependencyObject, _
                                                      e As DependencyPropertyChangedEventArgs)
        Dim frameworkElement As FrameworkElement = TryCast(dependencyObject, FrameworkElement)
        If frameworkElement Is Nothing Then
            Return
        End If
        If GetAnimationType(frameworkElement) <> AnimationType.None Then
            HookVisibilityChanges(frameworkElement)
        Else
            UnHookVisibilityChanges(frameworkElement)
        End If
    End Sub

    Private Shared Sub HookVisibilityChanges(frameworkElement As FrameworkElement)
        _hookedElements.Add(frameworkElement, False)
    End Sub

    Private Shared Sub UnHookVisibilityChanges(frameworkElement As FrameworkElement)
        If _hookedElements.ContainsKey(frameworkElement) Then
            _hookedElements.Remove(frameworkElement)
        End If
    End Sub

    Shared Sub New()
        UIElement.VisibilityProperty.AddOwner(GetType(FrameworkElement), _
                                              New FrameworkPropertyMetadata( _
                                                  Visibility.Visible, _
                                                  AddressOf VisibilityChanged, _
                                                  AddressOf CoerceVisibility))
    End Sub

    Private Shared Sub VisibilityChanged(dependencyObject As DependencyObject, _
                                         e As DependencyPropertyChangedEventArgs)
        'Nothing
    End Sub

    Private Shared Function CoerceVisibility(dependencyObject As DependencyObject, _
                                             baseValue As Object) As Object
        Dim frameworkElement As FrameworkElement = TryCast(dependencyObject, FrameworkElement)
        If frameworkElement Is Nothing Then
            Return baseValue
        End If
        Dim visibility As Visibility = DirectCast(baseValue, Visibility)
        If visibility = frameworkElement.Visibility Then
            Return baseValue
        End If
        If Not IsHookedElement(frameworkElement) Then
            Return baseValue
        End If
        If UpdateAnimationStartedFlag(frameworkElement) Then
            Return baseValue
        End If
        Dim doubleAnimation As DoubleAnimation = New DoubleAnimation() With _
                                                 {.Duration = New Duration(TimeSpan.FromMilliseconds(AnimationDuration))}
        AddHandler doubleAnimation.Completed, Sub(sender, eventArgs)
                                                  If visibility = Windows.Visibility.Visible Then
                                                      UpdateAnimationStartedFlag(frameworkElement)
                                                  Else
                                                      If BindingOperations.IsDataBound(frameworkElement, _
                                                                                       UIElement.VisibilityProperty) Then
                                                          Dim bindingValue As Binding = _
                                                              BindingOperations.GetBinding(frameworkElement, _
                                                                                           UIElement.VisibilityProperty)
                                                          BindingOperations.SetBinding(frameworkElement, _
                                                                                       UIElement.VisibilityProperty, bindingValue)
                                                      Else
                                                          frameworkElement.Visibility = visibility
                                                      End If
                                                  End If
                                              End Sub
        If visibility = Windows.Visibility.Collapsed OrElse visibility = Windows.Visibility.Hidden Then
            doubleAnimation.From = 1.0
            doubleAnimation.To = 0.0
        Else
            doubleAnimation.From = 0.0
            doubleAnimation.To = 1.0
        End If
        frameworkElement.BeginAnimation(UIElement.OpacityProperty, doubleAnimation)
        Return Windows.Visibility.Visible

    End Function

    Private Shared Function IsHookedElement(frameworkElement As FrameworkElement)
        Return _hookedElements.ContainsKey(frameworkElement)
    End Function

    Private Shared Function UpdateAnimationStartedFlag(frameworkElement As FrameworkElement)
        Dim animationStarted As Boolean = _hookedElements(frameworkElement)
        _hookedElements(frameworkElement) = Not animationStarted
        Return animationStarted
    End Function

End Class
<TextBlock x:Name="lblTest" own:VisibilityAnimation.AnimationType="Fade" Text="TEST" />

Visibilityが変わると透過しながら表示/非表示を行う

関連記事

【Cocos2d-x】iPhone実機でプロジェクトを動かすまで

Macを購入してCocos2d-xデビューしたが、 iPhone実機で動かすまでをメモ

記事を読む

ストアアプリ、UWPアプリをデスクトップアプリケーションから起動する

SendKeyなどを使って無理やり検索ウインドウへ指定した、起動方法しか知らなかったのでメモ(とんで

記事を読む

PHP executable not found. Install PHP 7 and add it to your PATH or set the php.executablePath setting

Visual Studio Code へ PHP IntelliSense 拡張をインストールし

記事を読む

【iPhoneアプリ】多言語対応させる2

今回はコード内の文字列を多言語化する ファイルを追加する。  

記事を読む

no image

No registered resource provider found for location ‘Japan East’ and API version ‘2.0’ for type ‘servers’.

Visual Studio から Azure Web Apps をデプロイするときに発生したエラーの

記事を読む

no image

【ストアアプリ】資格情報の保存と読み込み

こんにちは。 Windowsストアアプリで資格情報をセキュアに保存する方法について。

記事を読む

no image

SmallBasicで拡張ライブラリを使用する

こんにちは。 teratailにて以下の質問に遭遇しまして。 small basic の 拡

記事を読む

no image

Expression Encoder を組み込んだアプリケーションを配布する際のライセンス問題

Windowsアプリケーションにメディア編集機能を実装したい場合に、Expression Encod

記事を読む

Xamarin.FormsのTabbedPageでバッジを表示する

iOSのタブバーはNative側でバッジ機能があるのだが、Androidにはそもそもバッジが無いらし

記事を読む

【iPhoneアプリ】多言語対応させる1

iPhoneアプリを多言語対応(iPhone端末の言語設定によってアプリケーションの言語も切り替える

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

PAGE TOP ↑