【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

RPi3 OmxPlayer / VLC Player 連続再生2回目から映像が乱れる問題

Raspberry Pi 3 Model の Ubuntu や Raspbian で OmxPlay

記事を読む

【ストアアプリ】タイル通知(TileUpdateManager)について

こんにちは。 ストアアプリでタイル通知を行う方法を調べました。 前回のトースト通知と

記事を読む

no image

【VB.NET】DataGridViewで行の最大高を設定

DataGridViewにおける行の最大高さを設定するメモ 最大高さに満たない場合は内容を全て表示

記事を読む

no image

Desktop App Converter で作成したUWPアプリケーションをストアで公開したい

Twitterで掲題について調べている人がいらっしゃって、一緒に調べてみたのだが 案内されているペー

記事を読む

Visual Studio Team Services ダッシュボードを自動更新する

Visual Studio Team Services のダッシュボードでプロジェクトや運用状況のサ

記事を読む

Flowで毎月の定期タスク設定

Flow を使い始めてみた。 Requrrenceで時間をトリガーにすることが出来るがSecond

記事を読む

no image

FixedDocumentの印刷およびXPS形式での保存

こんにちは。 以前、XAMLファイルを帳票テンプレートとして動的ロードする記事を掲載しました。

記事を読む

no image

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

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

記事を読む

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

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

記事を読む

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

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

記事を読む

Message

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

PAGE TOP ↑