我怎么会做出/控制淡出时,它变得可见。
下面是我的失败尝试:
<Window x:Class="WadFileTester.Form1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="MyWindow" Title="WAD File SI Checker" Height="386" Width="563" WindowStyle="SingleBorderWindow" DragEnter="Window_DragEnter" DragLeave="Window_DragLeave" DragOver="Window_DragOver" Drop="Window_Drop" AllowDrop="True">
<Window.Resources>
<Style TargetType="ListView" x:Key="animatedList">
<Style.Triggers>
<DataTrigger Binding="{Binding Visibility}" Value="Visible">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:5"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ListView Name="listView1" Style="{StaticResource animatedList}" TabIndex="1" Margin="12,41,12,12" Visibility="Hidden">
</ListView>
</Grid>
</Window>
Answer 1:
我不知道如何在纯XAML一举两得动画(淡入和淡出)。 但是简单的淡出就可以实现相对简单。 与触发器替换DataTriggers,并删除ExitActions,因为他们是没有意义的淡出场景。 这是你拥有的一切:
<Style TargetType="FrameworkElement" x:Key="animatedList">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
但是,嘿,不要放弃。 如果你想支持动画我可以建议XAML后面小的编码。 我们做了一招后,我们会得到你想要的东西通过添加一行代码在XAML:
<Button Content="Fading button"
x:Name="btn"
loc:VisibilityAnimation.IsActive="True"/>
每当我们改变btn.Visibility从可见光到隐藏/折叠按钮时会淡出。 我们每次改变时间能见度背面的按钮将淡出。这一招将与任何FrameworkElement的(包括ListView的:))工作。
这里是VisibilityAnimation.IsActive附加属性的代码:
public class VisibilityAnimation : DependencyObject
{
private const int DURATION_MS = 200;
private static readonly Hashtable _hookedElements = new Hashtable();
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.RegisterAttached("IsActive",
typeof(bool),
typeof(VisibilityAnimation),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsActivePropertyChanged)));
public static bool GetIsActive(UIElement element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
return (bool)element.GetValue(IsActiveProperty);
}
public static void SetIsActive(UIElement element, bool value)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
element.SetValue(IsActiveProperty, value);
}
static VisibilityAnimation()
{
UIElement.VisibilityProperty.AddOwner(typeof(FrameworkElement),
new FrameworkPropertyMetadata(Visibility.Visible, new PropertyChangedCallback(VisibilityChanged), CoerceVisibility));
}
private static void VisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// So what? Ignore.
}
private static void OnIsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var fe = d as FrameworkElement;
if (fe == null)
{
return;
}
if (GetIsActive(fe))
{
HookVisibilityChanges(fe);
}
else
{
UnHookVisibilityChanges(fe);
}
}
private static void UnHookVisibilityChanges(FrameworkElement fe)
{
if (_hookedElements.Contains(fe))
{
_hookedElements.Remove(fe);
}
}
private static void HookVisibilityChanges(FrameworkElement fe)
{
_hookedElements.Add(fe, false);
}
private static object CoerceVisibility(DependencyObject d, object baseValue)
{
var fe = d as FrameworkElement;
if (fe == null)
{
return baseValue;
}
if (CheckAndUpdateAnimationStartedFlag(fe))
{
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.
var visibility = (Visibility)baseValue;
var da = new DoubleAnimation
{
Duration = new Duration(TimeSpan.FromMilliseconds(DURATION_MS))
};
da.Completed += (o, e) =>
{
// This will trigger value coercion again
// but CheckAndUpdateAnimationStartedFlag() function will reture true
// this time, and animation will not be triggered.
fe.Visibility = visibility;
// NB: Small problem here. This may and probably will brake
// binding to visibility property.
};
if (visibility == Visibility.Collapsed || visibility == Visibility.Hidden)
{
da.From = 1.0;
da.To = 0.0;
}
else
{
da.From = 0.0;
da.To = 1.0;
}
fe.BeginAnimation(UIElement.OpacityProperty, da);
return Visibility.Visible;
}
private static bool CheckAndUpdateAnimationStartedFlag(FrameworkElement fe)
{
var hookedElement = _hookedElements.Contains(fe);
if (!hookedElement)
{
return true; // don't need to animate unhooked elements.
}
var animationStarted = (bool) _hookedElements[fe];
_hookedElements[fe] = !animationStarted;
return animationStarted;
}
}
这里最重要的是CoerceVisibility()方法。 正如你所看到的衰落动画完成后,直到我们不允许更改此属性。
这个代码是没有线程安全也不无bug。 它唯一的目的是显示方向:)。 所以随意提高,编辑并获得声誉)。
Answer 2:
你不能直接使用Visibility属性的淡出,因为设置一个触发上会先隐藏/关闭的控制,那么它的动画。 所以基本上,你会得到一个倒塌的控制=>没有动画。
一个“可靠”的办法是引入新的依赖项属性(连接或没有),说IsOpen
和设置属性触发IsOpen=True
它具有:
EnterAction:
ExitAction:
- 能见度设置为可见的关键帧0和折叠/在最后的关键帧隐藏
- 淡出不透明度从1到0。
下面是一个例子:
<Style TargetType="{x:Type local:TCMenu}">
<Style.Resources>
<Storyboard x:Key="FadeInMenu">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="{x:Null}">
<DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="FadeOutMenu">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="{x:Null}">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="{x:Null}">
<DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsOpen" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FadeInMenu}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource FadeOutMenu}"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Collapsed" />
</Style>
Answer 3:
我意识到这个问题是有点老了,但我只现在已经读了它,我已经调整了由Anvaka给出的代码。 它支持结合可视性(仅当装订模式设置为双向)。 它还支持淡入淡出和2个不同的时间长度值。
这里是类:
public class VisibilityAnimation : DependencyObject
{
#region Private Variables
private static HashSet<UIElement> HookedElements = new HashSet<UIElement>();
private static DoubleAnimation FadeAnimation = new DoubleAnimation();
private static bool SurpressEvent;
private static bool Running;
#endregion
#region Attached Dependencies
public static readonly DependencyProperty IsActiveProperty = DependencyProperty.RegisterAttached("IsActive", typeof(bool), typeof(VisibilityAnimation), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsActivePropertyChanged)));
public static bool GetIsActive(UIElement element)
{
if (element == null) throw new ArgumentNullException("element");
return (bool)element.GetValue(IsActiveProperty);
}
public static void SetIsActive(UIElement element, bool value)
{
if (element == null) throw new ArgumentNullException("element");
element.SetValue(IsActiveProperty, value);
}
public static readonly DependencyProperty FadeInDurationProperty = DependencyProperty.RegisterAttached("FadeInDuration", typeof(double), typeof(VisibilityAnimation), new PropertyMetadata(0.5));
public static double GetFadeInDuration(UIElement e)
{
if (e == null) throw new ArgumentNullException("element");
return (double)e.GetValue(FadeInDurationProperty);
}
public static void SetFadeInDuration(UIElement e, double value)
{
if (e == null) throw new ArgumentNullException("element");
e.SetValue(FadeInDurationProperty, value);
}
public static readonly DependencyProperty FadeOutDurationProperty = DependencyProperty.RegisterAttached("FadeOutDuration", typeof(double), typeof(VisibilityAnimation), new PropertyMetadata(1.0));
public static double GetFadeOutDuration(UIElement e)
{
if (e == null) throw new ArgumentNullException("element");
return (double)e.GetValue(FadeOutDurationProperty);
}
public static void SetFadeOutDuration(UIElement e, double value)
{
if (e == null) throw new ArgumentNullException("element");
e.SetValue(FadeOutDurationProperty, value);
}
#endregion
#region Callbacks
private static void VisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// So what? Ignore.
// We only specified a property changed call-back to be able to set a coercion call-back
}
private static void OnIsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Get the framework element and leave if it is null
var fe = d as FrameworkElement;
if (fe == null) return;
// Hook the element if IsActive is true and unhook the element if it is false
if (GetIsActive(fe)) HookedElements.Add(fe);
else HookedElements.Remove(fe);
}
private static object CoerceVisibility(DependencyObject d, object baseValue)
{
if (SurpressEvent) return baseValue; // Ignore coercion if we set the SurpressEvent flag
var FE = d as FrameworkElement;
if (FE == null || !HookedElements.Contains(FE)) return baseValue; // Leave if the element is null or does not belong to our list of hooked elements
Running = true; // Set the running flag so that an animation does not change the visibility if another animation was started (Changing Visibility before the 1st animation completed)
// 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
Visibility NewValue = (Visibility)baseValue; // Get the new value
if (NewValue == Visibility.Visible) FadeAnimation.Duration = new Duration(TimeSpan.FromSeconds((double)d.GetValue(FadeInDurationProperty))); // Get the duration that was set for fade in
else FadeAnimation.Duration = new Duration(TimeSpan.FromSeconds((double)d.GetValue(FadeOutDurationProperty))); // Get the duration that was set for fade out
// Use an anonymous method to set the Visibility to the new value after the animation completed
FadeAnimation.Completed += (obj, args) =>
{
if (FE.Visibility != NewValue && !Running)
{
SurpressEvent = true; // SuppressEvent flag to skip coercion
FE.Visibility = NewValue;
SurpressEvent = false;
Running = false; // Animation and Visibility change is now complete
}
};
FadeAnimation.To = (NewValue == Visibility.Collapsed || NewValue == Visibility.Hidden) ? 0 : 1; // Set the to value based on Visibility
FE.BeginAnimation(UIElement.OpacityProperty, FadeAnimation); // Start the animation (it will only start after we leave the coercion method)
return Visibility.Visible; // We need to return Visible in order to see the fading take place, otherwise it just sets it to Collapsed/Hidden without showing the animation
}
#endregion
static VisibilityAnimation()
{
// Listen for visibility changes on all elements
UIElement.VisibilityProperty.AddOwner(typeof(FrameworkElement), new FrameworkPropertyMetadata(Visibility.Visible, new PropertyChangedCallback(VisibilityChanged), CoerceVisibility));
}
}
Answer 4:
我已经来这一个稍微不同的方式-我有雷人的答案的扩展版本, 这个问题增加了一个淡入()和淡出()扩展方法坍塌或显示元素作为适当的一切,然后代替使物体的可见我可以叫淡入()和淡出()在他们 - 它会工作的任何元素没有任何具体的动画代码。
public static T FadeFromTo(this UIElement uiElement, double fromOpacity,
double toOpacity, int durationInMilliseconds, bool loopAnimation,
bool showOnStart, bool collapseOnFinish)
{
var timeSpan = TimeSpan.FromMilliseconds(durationInMilliseconds);
var doubleAnimation =
new DoubleAnimation(fromOpacity, toOpacity,
new Duration(timeSpan));
if (loopAnimation)
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
uiElement.BeginAnimation(UIElement.OpacityProperty, doubleAnimation);
if (showOnStart)
{
uiElement.ApplyAnimationClock(UIElement.VisibilityProperty, null);
uiElement.Visibility = Visibility.Visible;
}
if (collapseOnFinish)
{
var keyAnimation = new ObjectAnimationUsingKeyFrames{Duration = new Duration(timeSpan) };
keyAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame(Visibility.Collapsed, KeyTime.FromTimeSpan(timeSpan)));
uiElement.BeginAnimation(UIElement.VisibilityProperty, keyAnimation);
}
return uiElement;
}
public static T FadeIn(this UIElement uiElement, int durationInMilliseconds)
{
return uiElement.FadeFromTo(0, 1, durationInMilliseconds, false, true, false);
}
public static T FadeOut(this UIElement uiElement, int durationInMilliseconds)
{
return uiElement.FadeFromTo(1, 0, durationInMilliseconds, false, false, true);
}
Answer 5:
这是用行为做最好
class AnimatedVisibilityFadeBehavior : Behavior<Border>
{
public Duration AnimationDuration { get; set; }
public Visibility InitialState { get; set; }
DoubleAnimation m_animationOut;
DoubleAnimation m_animationIn;
protected override void OnAttached()
{
base.OnAttached();
m_animationIn = new DoubleAnimation(1, AnimationDuration, FillBehavior.HoldEnd);
m_animationOut = new DoubleAnimation(0, AnimationDuration, FillBehavior.HoldEnd);
m_animationOut.Completed += (sender, args) =>
{
AssociatedObject.SetCurrentValue(Border.VisibilityProperty, Visibility.Collapsed);
};
AssociatedObject.SetCurrentValue(Border.VisibilityProperty,
InitialState == Visibility.Collapsed
? Visibility.Collapsed
: Visibility.Visible);
Binding.AddTargetUpdatedHandler(AssociatedObject, Updated);
}
private void Updated(object sender, DataTransferEventArgs e)
{
var value = (Visibility)AssociatedObject.GetValue(Border.VisibilityProperty);
switch (value)
{
case Visibility.Collapsed:
AssociatedObject.SetCurrentValue(Border.VisibilityProperty, Visibility.Visible);
AssociatedObject.BeginAnimation(Border.OpacityProperty, m_animationOut);
break;
case Visibility.Visible:
AssociatedObject.BeginAnimation(Border.OpacityProperty, m_animationIn);
break;
}
}
}
这是专门被应用到边界 - 我还没有尝试过的用户控件,但我希望这同样适用。
要使用它,你需要的交融互动的命名空间:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
并使用在要对行为的边界此标记:
<i:Interaction.Behaviors>
<Interactivity:AnimatedVisibilityFadeBehavior AnimationDuration="0:0:0.3" InitialState="Collapsed" />
</i:Interaction.Behaviors>
你需要在命名空间中添加对动作类太..
Answer 6:
很老了,但你能不能只链DoubleAnimations?
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:5"
/>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
Answer 7:
You may want to try AutoReverse property ... though I am not sure if it works the way you want it to.
This is what I found on MSDN :
When a timeline's AutoReverse property is set to true and its RepeatBehavior property causes it to repeat, each forward iteration is followed by a backward iteration. This makes one repetition. For example, a timeline with an AutoReverse value of true with an iteration Count of 2 would play forward once, then backwards, then forwards again, and then backwards again.
文章来源: WPF Fade Animation