C# 可视性更改动画:属性已由';框架元素';

C# 可视性更改动画:属性已由';框架元素';,c#,wpf,xaml,animation,frameworkelement,C#,Wpf,Xaml,Animation,Frameworkelement,我正在使用此代码设置可见性更改的动画 public class VisibilityAnimation : DependencyObject { public enum AnimationType { None, Fade } private const int AnimationDuration = 1000; private static readonly Dictionary<FrameworkElement

我正在使用此代码设置可见性更改的动画

public class VisibilityAnimation : DependencyObject
{
    public enum AnimationType
    {
        None,
        Fade
    }

    private const int AnimationDuration = 1000;

    private static readonly Dictionary<FrameworkElement, bool> _hookedElements =
        new Dictionary<FrameworkElement, bool>();

    public static AnimationType GetAnimationType(DependencyObject obj)
    {
        return (AnimationType)obj.GetValue(AnimationTypeProperty);
    }

    public static void SetAnimationType(DependencyObject obj, AnimationType value)
    {
        obj.SetValue(AnimationTypeProperty, value);
    }

    public static readonly DependencyProperty AnimationTypeProperty =
        DependencyProperty.RegisterAttached(
            "AnimationType",
            typeof(AnimationType),
            typeof(VisibilityAnimation),
            new FrameworkPropertyMetadata(AnimationType.None,
                new PropertyChangedCallback(OnAnimationTypePropertyChanged)));
    private static void OnAnimationTypePropertyChanged(
        DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement frameworkElement = dependencyObject as FrameworkElement;

        if (frameworkElement == null)
        {
            return;
        }

        // If AnimationType is set to True on this framework element, 
        if (GetAnimationType(frameworkElement) != AnimationType.None)
        {
            // Add this framework element to hooked list
            HookVisibilityChanges(frameworkElement);
        }
        else
        {
            // Otherwise, remove it from the hooked list
            UnHookVisibilityChanges(frameworkElement);
        }
    }
    private static void HookVisibilityChanges(FrameworkElement frameworkElement)
    {
        _hookedElements.Add(frameworkElement, false);
    }
    private static void UnHookVisibilityChanges(FrameworkElement frameworkElement)
    {
        if (_hookedElements.ContainsKey(frameworkElement))
        {
            _hookedElements.Remove(frameworkElement);
        }
    }
    static VisibilityAnimation()
    {
        // Here we "register" on Visibility property "before change" event
        UIElement.VisibilityProperty.AddOwner(
            typeof(FrameworkElement),
            new FrameworkPropertyMetadata(
                Visibility.Visible,
                VisibilityChanged,
                CoerceVisibility));

    }
    private static void VisibilityChanged(
        DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs e)
    {
        // Ignore
    }
    private static object CoerceVisibility(
        DependencyObject dependencyObject,
        object baseValue)
    {
        // Make sure object is a framework element
        FrameworkElement frameworkElement = dependencyObject as FrameworkElement;
        if (frameworkElement == null)
        {
            return baseValue;
        }

        // Cast to type safe value
        Visibility visibility = (Visibility)baseValue;

        // If Visibility value hasn't change, do nothing.
        // This can happen if the Visibility property is set using data binding 
        // and the binding source has changed but the new visibility value 
        // hasn't changed.
        if (visibility == frameworkElement.Visibility || visibility == Visibility.Collapsed) //Aggiungo da cri..x fare l'effetto solo sul fade in
        {
            return baseValue;
        }

        // If element is not hooked by our attached property, stop here
        if (!IsHookedElement(frameworkElement))
        {
            return baseValue;
        }

        // Update animation flag
        // If animation already started, don't restart it (otherwise, infinite loop)
        if (UpdateAnimationStartedFlag(frameworkElement))
        {
            return baseValue;
        }

        // If we get here, it means we have to start fade in or fade out animation. 
        // In any case return value of this method will be Visibility.Visible, 
        // to allow the animation.
        DoubleAnimation doubleAnimation = new DoubleAnimation
        {
            Duration = new Duration(TimeSpan.FromMilliseconds(AnimationDuration))
        };

        // When animation completes, set the visibility value to the requested 
        // value (baseValue)
        doubleAnimation.Completed += (sender, eventArgs) =>
        {
            if (visibility == Visibility.Visible)
            {
                // In case we change into Visibility.Visible, the correct value 
                // is already set, so just update the animation started flag
                UpdateAnimationStartedFlag(frameworkElement);
            }
            else
            {
                // This will trigger value coercion again 
                // but UpdateAnimationStartedFlag() function will reture true 
                // this time, thus animation will not be triggered. 
                if (BindingOperations.IsDataBound(frameworkElement,
                    UIElement.VisibilityProperty))
                {
                    // Set visiblity using bounded value
                    Binding bindingValue =
                        BindingOperations.GetBinding(frameworkElement,
                            UIElement.VisibilityProperty);
                    BindingOperations.SetBinding(frameworkElement,
                        UIElement.VisibilityProperty, bindingValue);
                }
                else
                {
                    // No binding, just assign the value
                    frameworkElement.Visibility = visibility;
                }
            }
        };

        if (visibility == Visibility.Collapsed || visibility == Visibility.Hidden)
        {
            // Fade out by animating opacity
            doubleAnimation.From = 1.0;
            doubleAnimation.To = 0.0;
        }
        else
        {
            // Fade in by animating opacity
            doubleAnimation.From = 0.0;
            doubleAnimation.To = 1.0;
        }

        // Start animation
        frameworkElement.BeginAnimation(UIElement.OpacityProperty, doubleAnimation);

        // Make sure the element remains visible during the animation
        // The original requested value will be set in the completed event of 
        // the animation
        return Visibility.Visible;
    }
    private static bool IsHookedElement(FrameworkElement frameworkElement)
    {
        return _hookedElements.ContainsKey(frameworkElement);
    }
    private static bool UpdateAnimationStartedFlag(FrameworkElement frameworkElement)
    {
        bool animationStarted = (bool)_hookedElements[frameworkElement];
        _hookedElements[frameworkElement] = !animationStarted;

        return animationStarted;
    }
公共类可见性动画:DependencyObject
{
公共枚举动画类型
{
没有一个
褪色
}
私有常量int AnimationDuration=1000;
专用静态只读词典=
新字典();
公共静态动画类型GetAnimationType(DependencyObject obj)
{
返回(AnimationType)obj.GetValue(AnimationTypeProperty);
}
公共静态void SetAnimationType(DependencyObject对象,AnimationType值)
{
对象设置值(AnimationTypeProperty,值);
}
公共静态只读DependencyProperty AnimationTypeProperty=
DependencyProperty.RegisterAttached(
“动画类型”,
typeof(AnimationType),
类型(可视性动画),
新的FrameworkPropertyMetadata(AnimationType.None,
新的PropertyChangedCallback(OnAnimationTypePropertyChanged));
AnimationTypePropertyChanged上的私有静态无效(
DependencyObject DependencyObject,
DependencyPropertyChangedEventArgs(附件e)
{
FrameworkElement FrameworkElement=作为FrameworkElement的dependencyObject;
if(frameworkElement==null)
{
返回;
}
//如果此框架元素上的AnimationType设置为True,
if(GetAnimationType(frameworkElement)!=AnimationType.None)
{
//将此框架元素添加到挂钩列表
挂钩可视性更改(框架元素);
}
其他的
{
//否则,请将其从挂钩列表中删除
无视觉变化(框架元素);
}
}
私有静态无效挂钩可见性更改(FrameworkElement FrameworkElement)
{
_hookedElements.Add(frameworkElement,false);
}
私有静态void UnHookVisibilityChanges(FrameworkElement FrameworkElement)
{
if(_hookedElements.ContainsKey(frameworkElement))
{
_钩形构件。移除(框架构件);
}
}
静态可视性动画()
{
//在这里,我们对可见性属性“更改前”事件进行“注册”
UIElement.VisibilityProperty.AddOwner(
类型(框架元件),
新框架属性元数据(
可见度,可见度,,
可视性改变,
强制性);
}
私有静态无效可见性已更改(
DependencyObject DependencyObject,
DependencyPropertyChangedEventArgs(附件e)
{
//忽略
}
私有静态对象强制性(
DependencyObject DependencyObject,
对象基本值)
{
//确保对象是框架元素
FrameworkElement FrameworkElement=作为FrameworkElement的dependencyObject;
if(frameworkElement==null)
{
返回基值;
}
//转换为类型安全值
可见性=(可见性)baseValue;
//如果“可见性”值未更改,则不执行任何操作。
//如果使用数据绑定设置可见性属性,则可能发生这种情况
//绑定源已更改,但新的可见性值
//没有改变。
如果(可见性==frameworkElement.visibility | |可见性==visibility.Collapsed)//Aggiungo da cri..x fare l'effetto solo sul淡入
{
返回基值;
}
//若元素并没有被我们附加的属性钩住,那个么就到此为止
if(!IsHookedElement(框架元素))
{
返回基值;
}
//更新动画标志
//如果动画已经启动,不要重新启动它(否则,无限循环)
if(UpdateAnimationStartedFlag(frameworkElement))
{
返回基值;
}
//如果我们到了这里,这意味着我们必须开始淡入淡出动画。
//在任何情况下,此方法的返回值都将是Visibility.Visible,
//以允许动画。
DoubleAnimation DoubleAnimation=新的DoubleAnimation
{
持续时间=新的持续时间(TimeSpan.From毫秒(AnimationDuration))
};
//动画完成后,将可见性值设置为请求的值
//价值(基本价值)
doubleAnimation.Completed+=(发送方,事件参数)=>
{
如果(可见性==可见性.Visible)
{
//如果我们更改为Visibility.Visible,则为正确的值
//已设置,因此只需更新动画开始标志
UpdateAnimationStartedFlag(frameworkElement);
}
其他的
{
//这将再次触发值强制
//但是UpdateAnimationStartedFlag()函数将返回true
//这一次,将不会触发动画。
if(BindingOperations.IsDataBound)(frameworkElement,
UIElement.VisibilityProperty)
{
//使用有界值设置可见性
绑定值=
BindingOperations.GetBinding(frameworkElement,
UIElement.VisibilityProperty);
BindingOperations.SetBinding(frameworkElement,
UIElement.VisibilityProperty,bindingValue);
}
其他的
{
//没有绑定,只需赋值
框架元素。可见性=可见性;
}
}
};
如果(可见性==可见性.折叠| |可见性==可见性.隐藏)
{
//通过设置不透明度动画淡出
doubleAnimation.From=1.0;
doubleAnimation.To=0.0;
}
static VisibilityAnimation()
{
    // Here we "register" on Visibility property "before change" event
    UIElement.VisibilityProperty.AddOwner(
        typeof(VisibilityAnimation),
        new FrameworkPropertyMetadata(
            Visibility.Visible,
            VisibilityChanged,
            CoerceVisibility));

}
    static VisibilityAnimation()
    {
        // Here we "register" on Visibility property "before change" event
        var desc = DependencyPropertyDescriptor.FromProperty(UIElement.VisibilityProperty, typeof(FrameworkElement));
        desc.DesignerCoerceValueCallback += CoerceVisibility;