【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が変わると透過しながら表示/非表示を行う

関連記事

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

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

記事を読む

no image

UWPでローカルにNoSQLデータベースを作成したい

LiteDBを使う CRUDの例 公式サンプルのとおりやるとデータソース指定のときに権限エ

記事を読む

【iPhoneアプリ】自分のiPhoneへインストールする方法

自作のiPhoneアプリを自分のiPhone上で動作させたい場合の手順をメモ ・iOS Dev

記事を読む

Docker for Windows で ドライブ共有が出来ない

Shared Drives タブで Cドライブにチェックをして Apply を押す。 認証ダイ

記事を読む

no image

Microsoft.Expression.Encoderで動画のフレーム画像を取得

動画ファイルから指定したフレーム画像を取得する。 Microsoft.Expression.Enco

記事を読む

no image

Microsoft Bot Frameworkでテキストメッセージではなく、添付ファイルを使用する

activity.Attachmentsに添付ファイル入っている。 ContentTypeで画像か判

記事を読む

no image

【Xcode】Capabilities全項目【v6.1時点】

Capabilitiesの各項目が何を示しているのか よくわからなかった、かつ日本語のサイトが少な

記事を読む

SIPSorceryにて、「型 ‘log4net.ILog’ が参照されていないアセンブリで定義されています。」

ある時、SIPクライアントの開発を行っていた。 SIPクライアントライブラリの選定にあたって S

記事を読む

【XAML】フォントサイズを自動縮小して全体を表示

Viewboxを親にするだけ。 拡大・縮小方法はStretch, StretchDirec

記事を読む

no image

This project references NuGet package(s) that are missing on this computer.

.nugetフォルダが設定されているソリューションから一部プロジェクトのみを抜き出すと発生する。 N

記事を読む

Message

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

PAGE TOP ↑