【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

Microsoft Flow 入門

社内LT用

記事を読む

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

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

記事を読む

Minnow Board Turbot + Windows 10 IoT Core をSSD上で動作させる

MinnowBoard は SATAが搭載されているので、SSDなどが利用できる。 通常はSDカード

記事を読む

no image

Windows8.1 64bitにVB6.0開発環境を構築メモ

MSDNフォーラムの、この投稿はとても素晴らしいです。 windows 8 64bit

記事を読む

no image

UWPのScrollViewerでスクロール位置の同期を行うメモ

複数のScrollViewerのスクロール位置を同期したい場合、WPFではScrollChanged

記事を読む

Xamarin.Forms で NavigationPage を PushModalAsync すると例外が発生するときがある

Forms 2.3.4.231 Mapコントロールがあるページで、NavigationPage

記事を読む

no image

【.NET】正規表現の復習

正規表現エンジン System.Text.RegularExpressions.Regexオブジェ

記事を読む

no image

【XAML/VB.NET】XAMLファイルを帳票フォーマットとして使用する

掲題について。結論としてはFixedPageをルートとするXAMLファイルを XamlReader

記事を読む

no image

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

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

記事を読む

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

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

記事を読む

Message

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

PAGE TOP ↑