简体   繁体   English

怎么用WPF中的Frame控件做过渡效果?

[英]How do you do transition effects using the Frame control in WPF?

I thought this would be easy but I guess not.我认为这很容易,但我想不是。

I have 2 pages that load in my frame control.我有 2 个页面加载到我的框架控件中。 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.我希望能够从一页到下一页有一个很好的幻灯片效果,或者只是一个简单的淡入效果。

Can't seem to find this anywhere on the internets.似乎无法在互联网上的任何地方找到这个。

Update 1 The accepted answer is good, but I found an even better one here.更新 1接受的答案很好,但我在这里找到了更好的答案。 http://www.japf.fr/2008/07/8/comment-page-1/ http://www.japf.fr/2008/07/8/comment-page-1/

Update 2 If you can believe it I found an even better solution.更新 2如果您能相信,我找到了一个更好的解决方案。
http://fluidkit.codeplex.com/ http://fluidkit.codeplex.com/

There is a similar problem discussed here: Transition Fade Animation When Navigating To Page Using 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希望这有帮助,问候

My answer is the improved version of the answer given by serge_gebunko.我的答案是 serge_gebunko 给出的答案的改进版本。
It gives you the Sliding left and right effect .它为您提供左右滑动效果

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);
            }

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 .在 Silverlight 中,我通过使用Silverlight Toolkit 中的 TransitioningContentControl 实现了页面之间的这种类型的滑动过渡效果。 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.如果您不想花时间定义自定义故事板,它还包括一些默认(淡入淡出/向上/向下)过渡。

I realize that you are working with WPF and that the TransitioningContentControl is not available in WPF or in the WPF Toolkit.我意识到您正在使用 WPF 并且 TransitioningContentControl 在 WPF 或 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.但是,将此控件移植到 WPF 或至少制作一个执行类似操作的控件可能并不太困难。 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.浏览源代码,如果您有时间,它看起来可能是可行的,并且它是您可以在其他地方重用的控件类型。

The source code is here for the Silverlight version and Jesse Liberty has a nice tutorial which walks through using the control in Silverlight. Silverlight 版本的源代码在这里,Jesse Liberty 有一个很好的教程,介绍如何使用 Silverlight 中的控件。

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 还很陌生,所以如果有任何可以改进这个答案的东西,请在下面发布

I just applied a double animation to the OpacityProperty of the frame content whenever it's navigating.我只是在OpacityProperty时对框架内容的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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何覆盖不在(xaml / wpf)中的网格上的控件 - How do you overlay a control over a grid that it is not in (xaml/wpf) 如何在设计模式下调试 WPF 用户控件? - How do you debug a WPF user control in design mode? 您如何在WPF日历控件上检测到自动的Month转换? - How do you detect an automatic Month shift on the WPF Calendar control? 您如何从基本WPF用户控件继承从属属性到继承的新用户控件? - How do you inherit Dependent Properties from a base WPF User Control to a new User Control that is inherited? 如何使用 XAML 向 WPF 按钮添加弹出消息 - How do you add a flyout message to a WPF button using XAML 如何使用 WPF 突出显示 combobox 中的项目? - How do you highlight an item in a combobox using WPF? 如何使用C#/ WPF制作模态ProgressBar? - How do you make modal ProgressBar using C#/WPF? 如何使用 wpf 代码隐藏在列表框中隐藏单个列表框项目? - How do you hide a single listboxitem in a listbox using wpf codebehind? 如何使用其控件ID获得子窗口? - How do you get a child window using its control ID? WPF自定义控件-如何从静态ObservableCollection绑定列表框? - WPF Custom Control - How do you bind a listbox from a static ObservableCollection?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM