web-dev-qa-db-ja.com

WPFのフレームコントロールを使用してトランジション効果をどのように実行しますか?

これは簡単だと思いましたが、そうではないと思います。

フレームコントロールにロードするページが2つあります。あるページから次のページへの素敵なスライド効果、または単純なフェードイン効果のいずれかを実現したいと考えています。

インターネットのどこにもこれを見つけることができないようです。

更新1受け入れられた答えは良いですが、ここでさらに良い答えを見つけました。 http://www.japf.fr/2008/07/8/comment-page-1/

アップデート2信じられれば、もっと良い解決策を見つけました。
http://fluidkit.codeplex.com/

17
Donny V.

ここで説明する同様の問題があります。 ページに移動するときのトランジションフェードアニメーション ここで説明する手法を使用すると、新しいページを移動するたびにフレームコントロールをスライド/移動できます。このようなSmth:

xaml:

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

これがお役に立てば幸いです

20
serge_gubenko

私の答えは、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);
            }
10
Wong Jia Hau

これはおそらく最善の答えではありませんが、おそらくあなたに役立つか、少なくともあなたにいくつかのアイデアを与えるでしょう。 Silverlightでは、 Silverlight Toolkit のTransitioningContentControlを使用して、ページ間のこのタイプのスライド遷移効果を実現しました。これは基本的に、コンテンツが変更されるたびに古いコンテンツと新しいコンテンツの間を移行するための視覚的な状態でカスタムストーリーボードを定義できるコンテンツコントロールです。カスタムストーリーボードを定義するのに時間をかけたくない場合は、いくつかのデフォルト(フェード/アップ/ダウン)トランジションも含まれています。

WPFを使用していて、TransitioningContentControlがWPFまたはWPFツールキットで使用できないことを認識しています。ただし、このコントロールをWPFに移植すること、または少なくとも同様のことを行うコントロールを作成することはそれほど難しくないかもしれません。ソースを一瞥すると、時間があれば実行可能であるように見えます。これは、他の場所で再利用できるタイプのコントロールです。

ソースコードはここにあります Silverlightバージョンの場合、Jesse Libertyには 素敵なチュートリアル があり、Silverlightのコントロールの使用について説明しています。

1
Dan Auclair

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はかなり新しいので、この回答を改善できることがあれば、以下に投稿してください。

0
Homa Abdo