我认为这很容易,但我想不会。
我有 2 个页面加载到我的框架控件中。我希望能够从一页到下一页有一个很好的幻灯片效果,或者只是一个简单的淡入效果。
似乎在互联网上的任何地方都找不到这个。
更新 1 接受的答案很好,但我在这里找到了更好的答案。 http://www.japf.fr/2008/07/8/comment-page-1/
更新 2
如果你能相信我找到了一个更好的解决方案。
http://fluidkit.codeplex.com/
我认为这很容易,但我想不会。
我有 2 个页面加载到我的框架控件中。我希望能够从一页到下一页有一个很好的幻灯片效果,或者只是一个简单的淡入效果。
似乎在互联网上的任何地方都找不到这个。
更新 1 接受的答案很好,但我在这里找到了更好的答案。 http://www.japf.fr/2008/07/8/comment-page-1/
更新 2
如果你能相信我找到了一个更好的解决方案。
http://fluidkit.codeplex.com/
这里讨论了一个类似的问题:导航到页面时的过渡淡入淡出动画使用那里描述的技术,您可以在每次导航新页面时滑动\移动框架控件。像这样:
xml:
...
<Frame Name = "frame" Navigating="frame_Navigating">
...
代码:
...
private bool _allowDirectNavigation = false;
private NavigatingCancelEventArgs _navArgs = null;
private Duration _duration = new Duration(TimeSpan.FromSeconds(1));
private double _oldHeight = 0;
private void frame_Navigating(object sender, NavigatingCancelEventArgs e)
{
if (Content!=null && !_allowDirectNavigation)
{
e.Cancel = true;
_navArgs = e;
_oldHeight = frame.ActualHeight;
DoubleAnimation animation0 = new DoubleAnimation();
animation0.From = frame.ActualHeight;
animation0.To = 0;
animation0.Duration = _duration;
animation0.Completed += SlideCompleted;
frame.BeginAnimation(HeightProperty, animation0);
}
_allowDirectNavigation = false;
}
private void SlideCompleted(object sender, EventArgs e)
{
_allowDirectNavigation = true;
switch (_navArgs.NavigationMode)
{
case NavigationMode.New:
if (_navArgs.Uri == null)
frame.Navigate(_navArgs.Content);
else
frame.Navigate(_navArgs.Uri);
break;
case NavigationMode.Back:
frame.GoBack();
break;
case NavigationMode.Forward:
frame.GoForward();
break;
case NavigationMode.Refresh:
frame.Refresh();
break;
}
Dispatcher.BeginInvoke(DispatcherPriority.Loaded,
(ThreadStart)delegate()
{
DoubleAnimation animation0 = new DoubleAnimation();
animation0.From = 0;
animation0.To = _oldHeight;
animation0.Duration = _duration;
frame.BeginAnimation(HeightProperty, animation0);
});
}
...
希望这会有所帮助,问候
我的答案是 serge_gebunko 给出的答案的改进版本。
它为您提供左右滑动效果。
XAML
...
<Frame Name = "MainFrame" Navigating="MainFrame_OnNavigating">
...
C#
private void MainFrame_OnNavigating(object sender, NavigatingCancelEventArgs e) {
var ta = new ThicknessAnimation();
ta.Duration = TimeSpan.FromSeconds(0.3);
ta.DecelerationRatio = 0.7;
ta.To = new Thickness(0 , 0 , 0 , 0);
if (e.NavigationMode == NavigationMode.New) {
ta.From = new Thickness(500, 0, 0, 0);
}
else if (e.NavigationMode == NavigationMode.Back) {
ta.From = new Thickness(0 , 0 , 500 , 0);
}
(e.Content as Page).BeginAnimation(MarginProperty , ta);
}
这可能不是最好的答案,但它可能对你有帮助,或者至少给你一些想法。在 Silverlight 中,我通过使用Silverlight Toolkit中的 TransitioningContentControl 实现了页面之间的那种滑动过渡效果。它是一个内容控件,基本上可以让您在视觉状态下定义自定义故事板,以便在内容更改时在旧内容和新内容之间进行转换。如果您不想花时间定义自定义故事板,它还包括一些默认(淡入淡出/上/下)过渡。
我意识到您正在使用 WPF,并且在 WPF 或 WPF 工具包中不提供 TransitioningContentControl。但是,将此控件移植到 WPF 或至少制作一个执行类似操作的控件可能并不太难。浏览一下源代码,如果您有时间,它看起来可能是可行的,并且它是您可以在其他地方重用的控件类型。
Silverlight 版本的源代码在此处,Jesse Liberty 有一个很好的教程,其中介绍了如何使用 Silverlight 中的控件。
我搜索了一个 mvvm 友好的答案,但我没有找到任何答案,所以我使用附加属性制作了自己的答案:
public class FrameAnimator : DependencyObject
{
public static readonly DependencyProperty FrameNextNavigationStotryboardProperty = DependencyProperty.RegisterAttached("FrameNextNavigationStotryboard", typeof(Storyboard), typeof(FrameAnimator), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsMeasure, FrameNextNavigationStotryboardProprtyChanged));
private static void FrameNextNavigationStotryboardProprtyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Frame)
{
Storyboard st = GetFrameNextNavigationStotryboard(d);
if (st != null)
{
(d as Frame).Navigating += (sm, ar) =>
{
if (ar.NavigationMode != System.Windows.Navigation.NavigationMode.Back)
{
st.Begin((d as Frame));
}
};
}
}
}
public static void SetFrameNextNavigationStotryboard(DependencyObject control, Storyboard st)
{
control.SetValue(FrameNextNavigationStotryboardProperty, st);
}
public static Storyboard GetFrameNextNavigationStotryboard(DependencyObject control)
{
var val = control.GetValue(FrameNextNavigationStotryboardProperty);
if (val is Storyboard)
return (Storyboard)val;
return null;
}
/// <summary>
/// /////////////////////////////////////////////////////////////////////
/// </summary>
public static readonly DependencyProperty FrameBackNavigationStotryboardProperty = DependencyProperty.RegisterAttached("FrameBackNavigationStotryboard", typeof(Storyboard), typeof(FrameAnimator), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsMeasure, FrameBackNavigationStotryboardProprtyChanged));
private static void FrameBackNavigationStotryboardProprtyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Frame)
{
Storyboard st = GetFrameBackNavigationStotryboard(d);
if (st != null)
{
(d as Frame).Navigating += (sm, ar) =>
{
if (ar.NavigationMode == System.Windows.Navigation.NavigationMode.Back)
{
st.Begin((d as Frame));
}
};
}
}
}
public static void SetFrameBackNavigationStotryboard(DependencyObject control, Storyboard st)
{
control.SetValue(FrameBackNavigationStotryboardProperty, st);
}
public static Storyboard GetFrameBackNavigationStotryboard(DependencyObject control)
{
var val = control.GetValue(FrameBackNavigationStotryboardProperty);
if (val is Storyboard)
return (Storyboard)val;
return null;
}
}
用法 :
<Window x:Class="sqlTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:fr="clr-namespace:YourNameSpace;assembly=YourNameSpace">
<Window.Resources>
<system:Double x:Key="TValue">
1000
</system:Double>
<system:Double x:Key="NTValue">
-1000
</system:Double>
<Storyboard x:Key="NavNextAnim">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.800"/>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="0" From="{StaticResource ResourceKey=TValue}" Duration="0:0:0.3"/>
</Storyboard>
<Storyboard x:Key="NavBackAnim">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.800"/>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="0" From="{StaticResource ResourceKey=NTValue}" Duration="0:0:0.3"/>
</Storyboard>
</Window.Resources>
<Frame
fr:FrameAnimator.FrameNextNavigationStotryboard="{StaticResource ResourceKey=NavNextAnim}"
fr:FrameAnimator.FrameBackNavigationStotryboard="{StaticResource ResourceKey=NavBackAnim}">
<Frame.RenderTransform>
<TranslateTransform/>
</Frame.RenderTransform>
</Frame>
</Window>
我对 mvvm 相当陌生,所以如果有什么可以改进这个答案的,请在下面发布
OpacityProperty
我只是在导航时对框架内容应用了双重动画。
private void Frame_Navigating(object sender, NavigatingCancelEventArgs e)
{
var fa = new DoubleAnimation(0, 1, TimeSpan.FromSeconds(0.3));
(e.Content as Page).BeginAnimation(OpacityProperty, fa);
}