19

我认为这很容易,但我想不会。

我有 2 个页面加载到我的框架控件中。我希望能够从一页到下一页有一个很好的幻灯片效果,或者只是一个简单的淡入效果。

似乎在互联网上的任何地方都找不到这个。

更新 1 接受的答案很好,但我在这里找到了更好的答案。 http://www.japf.fr/2008/07/8/comment-page-1/

更新 2 如果你能相信我找到了一个更好的解决方案。
http://fluidkit.codeplex.com/

4

5 回答 5

24

这里讨论了一个类似的问题:导航到页面时的过渡淡入淡出动画使用那里描述的技术,您可以在每次导航新页面时滑动\移动框架控件。像这样:

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

希望这会有所帮助,问候

于 2010-01-26T04:58:02.557 回答
11

我的答案是 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);
            }
于 2017-04-10T08:42:49.930 回答
1

这可能不是最好的答案,但它可能对你有帮助,或者至少给你一些想法。在 Silverlight 中,我通过使用Silverlight Toolkit中的 TransitioningContentControl 实现了页面之间的那种滑动过渡效果。它是一个内容控件,基本上可以让您在视觉状态下定义自定义故事板,以便在内容更改时在旧内容和新内容之间进行转换。如果您不想花时间定义自定义故事板,它还包括一些默认(淡入淡出/上/下)过渡。

我意识到您正在使用 WPF,并且在 WPF 或 WPF 工具包中不提供 TransitioningContentControl。但是,将此控件移植到 WPF 或至少制作一个执行类似操作的控件可能并不太难。浏览一下源代码,如果您有时间,它看起来可能是可行的,并且它是您可以在其他地方重用的控件类型。

Silverlight 版本的源代码在此处,Jesse Liberty 有一个很好的教程,其中介绍了如何使用 Silverlight 中的控件。

于 2010-01-26T04:53:19.830 回答
1

我搜索了一个 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 相当陌生,所以如果有什么可以改进这个答案的,请在下面发布

于 2020-01-13T11:26:20.753 回答
0

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);
}
于 2021-11-23T01:24:32.437 回答