C# 怎么用WPF中的Frame控件做过渡效果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2135113/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you do transition effects using the Frame control in WPF?
提问by Donny V.
I thought this would be easy but I guess not.
我认为这很容易,但我想不是。
I have 2 pages that load in my frame control. I want to be able to either have a nice slide effect from one page to the next or just a simple fade-In effect.
我有 2 个页面加载到我的框架控件中。我希望能够从一页到下一页有一个很好的幻灯片效果,或者只是一个简单的淡入效果。
Can't seem to find this anywhere on the internets.
似乎无法在互联网上的任何地方找到这个。
Update 1The accepted answer is good, but I found an even better one here. http://www.japf.fr/2008/07/8/comment-page-1/
更新 1接受的答案很好,但我在这里找到了更好的答案。 http://www.japf.fr/2008/07/8/comment-page-1/
Update 2If you can believe it I found an even better solution.
http://fluidkit.codeplex.com/
更新 2如果您能相信,我找到了一个更好的解决方案。
http://fluidkit.codeplex.com/
采纳答案by serge_gubenko
There is a similar problem discussed here: Transition Fade Animation When Navigating To PageUsing the technique described there you can slide\move your frame control each time a new page is navigated. Smth like this:
这里讨论了一个类似的问题:导航到页面时的过渡淡入淡出动画使用那里描述的技术,您可以在每次导航新页面时滑动\移动框架控件。像这样:
xaml:
xml:
...
<Frame Name = "frame" Navigating="frame_Navigating">
...
code:
代码:
...
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);
});
}
...
hope this helps, regards
希望这有帮助,问候
回答by Dan Auclair
This probably isn't the best answer, but it maybe helpful to you or at least give you some ideas. In Silverlight I have achieved that type of sliding transition effect between pages by using the TransitioningContentControl from the Silverlight Toolkit. It is a content control which basically lets you define a custom storyboard in a visual state for a transition between the old and new content whenever the content changes. It also includes some default (fade/up/down) transitions if you don't want to take the time to define a custom storyboard.
这可能不是最好的答案,但它可能对您有帮助或至少给您一些想法。在 Silverlight 中,我通过使用Silverlight Toolkit 中的 TransitioningContentControl 实现了页面之间的这种类型的滑动过渡效果。它是一个内容控件,基本上允许您在视觉状态下定义自定义故事板,以便在内容更改时在新旧内容之间进行转换。如果您不想花时间定义自定义故事板,它还包括一些默认(淡入淡出/向上/向下)过渡。
I realize that you are working with WPF and that the TransitioningContentControl is not available in WPF or in the WPF Toolkit. However, it may not be too difficult to port this control over to WPF or at least make one that does something similar. Glancing over the source it looks like it may be doable if you have the time and it is the type of control you may reuse in other places.
我意识到您正在使用 WPF 并且 TransitioningContentControl 在 WPF 或 WPF Toolkit 中不可用。但是,将此控件移植到 WPF 或至少制作一个执行类似操作的控件可能并不太困难。浏览源代码,如果您有时间,它看起来可能是可行的,并且它是您可以在其他地方重用的控件类型。
The source code is herefor the Silverlight version and Jesse Liberty has a nice tutorialwhich walks through using the control in Silverlight.
Silverlight 版本的源代码在这里,Jesse Liberty 有一个很好的教程,介绍如何使用 Silverlight 中的控件。
回答by Wong Jia Hau
My answer is the improved version of the answer given by serge_gebunko.
It gives you the Sliding left and right effect.
我的答案是 serge_gebunko 给出的答案的改进版本。
它为您提供左右滑动效果。
XAML
XAML
...
<Frame Name = "MainFrame" Navigating="MainFrame_OnNavigating">
...
C#
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);
}
回答by Wong Jia Hau
i searched for a mvvm friendly answer and i didn't find any so i made my own using an attached property:
我搜索了一个 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;
}
}
Usage :
用法 :
<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>
Am fairly new to mvvm so if there is any thing that can improve this answer please post it below
我对 mvvm 还很陌生,所以如果有任何可以改进这个答案的东西,请在下面发布