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

関連記事

no image

【WPF/XAML】Buttonのテキスト(Content)を自動改行/折り返しさせる

今更WPFを触りはじめました。 それまではほぼ.NETは2.0止まりというオワコン開発者です。

記事を読む

no image

Xamarin.Forms で ScrollView の中に Map を配置したとき、Androidで地図のスクロールが出来なくなる

iOSは問題ないけど、AndroidはScrollViewにタッチを持ってかれてる感じ。 カスタ

記事を読む

Xamarin.Androidで起動時にアプリケーションを起動

RECEIVE_BOOT_COMPLETEDの権限必要 ActionBootCompleted を

記事を読む

Visual Studio 2015 Express の Language Pack

探してみたけど見当たらなかったのでメモ残し。 Visual Studio 2015 には言語パック

記事を読む

no image

Windows 10 IoT 系の概要、エディション、入手方法などを一度整理

Windows 10 IoT にここ最近振り回されているので、ここまで解釈した内容にて、まとメモ 正

記事を読む

no image

【.NET】イベントのサブスクライブとサブスクライブ解除

.NETでイベントをハンドルする方法 サブスクライブ void CustomEven

記事を読む

【VisualStudio2015】UWPアプリケーションのXAMLデザイナにて「パッケージを登録できませんでした。」

VisualStudio2015 / UWPアプリケーション / XAMLデザイナ / エラー のメ

記事を読む

IntelliTestはどこまでカバーしてくれるのか

私はレガシーな開発環境・案件が多かったのですが、 この頃、ユニットテストを利用する機会が増えてきま

記事を読む

Xcode標準テンプレート

Xcodeで新規Projectを作成した時にテンプレートを選ぶことが出来る。 「Choose a

記事を読む

【WPF/XAML】Colorsクラスのカラーテーブル

http://msdn.microsoft.com/ja-jp/library/system.win

記事を読む

Message

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

PAGE TOP ↑