WPF如何实现类似iPhone界面切换的效果 (version .1)

转自:http://blog.csdn.net/fallincloud/article/details/6968764

在论坛上见到有人提出了这个问题(WPF实现点击横向切换界面

我简单地做了个Sample。

效果图1:

效果图1

 

效果图2:

效果图2

设计思路

将这多个界面放入一个Orientation为Horizontal的StackPanel当中,点击Next时,里面所有控件执行TranslteTransform动画。

实现

xaml

 

 

[html] view plaincopy
 
  1. <Window x:Class="WPFNavigation.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         Title="MainWindow" Height="350" Width="400">  
  5.     <Grid>  
  6.         <Grid.RowDefinitions>  
  7.             <RowDefinition Height="*"></RowDefinition>  
  8.             <RowDefinition Height="Auto"></RowDefinition>  
  9.         </Grid.RowDefinitions>  
  10.         <StackPanel Orientation="Horizontal"   
  11.                     x:Name="NavigationPanel"  
  12.                     Height="300"   
  13.                     HorizontalAlignment="Left"  
  14.                     VerticalAlignment="Top">  
  15.               
  16.             <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"  
  17.                   Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"  
  18.                   Background="Blue" >  
  19.                 <TextBlock FontSize="36">Page1</TextBlock>  
  20.             </Grid>  
  21.             <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"  
  22.                   Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"  
  23.                   Background="Violet">  
  24.                 <TextBlock FontSize="36">Page2</TextBlock>  
  25.             </Grid>  
  26.             <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"  
  27.                   Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"  
  28.                   Background="Purple" >  
  29.                 <TextBlock FontSize="36">Page3</TextBlock>  
  30.             </Grid>  
  31.         </StackPanel>  
  32.           
  33.         <StackPanel Grid.Row="1"  Orientation="Horizontal" >  
  34.             <Button Content="Previous" x:Name="ButtonPreviousPage" Click="ButtonPreviousPage_Click"></Button>  
  35.             <Button Content="Next" x:Name="ButtonNextPage" Click="ButtonNextPage_Click"></Button>             
  36.         </StackPanel>  
  37.     </Grid>  
  38. </Window>  

 

 

cs中

 

 

[csharp] view plaincopy
 
    1. /// <summary>  
    2. /// Interaction logic for MainWindow.xaml  
    3. /// </summary>  
    4. public partial class MainWindow : Window  
    5. {  
    6.   
    7.     private static readonly double COUNT_PAGE = 3;  
    8.     private TranslateTransform NavigationPanelTranslateTransform;  
    9.   
    10.     public MainWindow()  
    11.     {  
    12.         InitializeComponent();  
    13.   
    14.         NavigationPanelTranslateTransform = new TranslateTransform();  
    15.           
    16.         this.Loaded += new RoutedEventHandler(MainWindow_Loaded);  
    17.     }  
    18.   
    19.     void MainWindow_Loaded(object sender, RoutedEventArgs e)  
    20.     {  
    21.         foreach (FrameworkElement fe in NavigationPanel.Children)  
    22.         {  
    23.             fe.RenderTransform = NavigationPanelTranslateTransform;  
    24.         }  
    25.   
    26.         DeterminButtonStates();  
    27.     }  
    28.   
    29.     private void DeterminButtonStates()  
    30.     {  
    31.         double currentTranX = NavigationPanelTranslateTransform.X;  
    32.   
    33.         if (currentTranX >= 0)  
    34.         {  
    35.             ButtonPreviousPage.IsEnabled = false;  
    36.         }  
    37.         else if (currentTranX <= -(COUNT_PAGE - 1) * this.ActualWidth)  
    38.         {  
    39.             ButtonNextPage.IsEnabled = false;  
    40.         }  
    41.         else  
    42.         {  
    43.             ButtonPreviousPage.IsEnabled = true;  
    44.             ButtonNextPage.IsEnabled = true;  
    45.         }  
    46.     }  
    47.   
    48.     private void ButtonPreviousPage_Click(object sender, RoutedEventArgs e)  
    49.     {  
    50.         double currentTranX = NavigationPanelTranslateTransform.X;  
    51.           
    52.         DoubleAnimation da = new DoubleAnimation(currentTranX, currentTranX+this.ActualWidth, TimeSpan.FromMilliseconds(250));  
    53.         da.Completed += (o1, e1) =>  
    54.             {  
    55.                 DeterminButtonStates();  
    56.             };  
    57.   
    58.         NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);           
    59.     }  
    60.   
    61.     private void ButtonNextPage_Click(object sender, RoutedEventArgs e)  
    62.     {  
    63.         double currentTranX = NavigationPanelTranslateTransform.X;  
    64.   
    65.         DoubleAnimation da = new DoubleAnimation(currentTranX, currentTranX - this.ActualWidth, TimeSpan.FromMilliseconds(250));  
    66.         da.Completed += (o1, e1) =>  
    67.         {  
    68.             DeterminButtonStates();  
    69.         };  
    70.   
    71.         NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);       
    72.     }  
    73. }  

 

 

WPF如何实现类似iPhone界面切换的效果 (version .2)

转自:http://blog.csdn.net/fallincloud/article/details/6969329

前面写了篇WPF如何实现类似iPhone界面切换的效果 (version .1)

现在又花了点时间重构了下,将动画的效果和Previous和Next这两个按钮的状态控制都封装了起来,效果依然和前面一样

不过重用性高了许多。使用方法如下:

 

XAML:

 

[html] view plaincopy
 
  1. <Window x:Class="WPFNavigation.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         xmlns:local="clr-namespace:WPFNavigation"  
  5.         Title="MainWindow" Height="350" Width="400">  
  6.     <Grid>  
  7.         <Grid.RowDefinitions>  
  8.             <RowDefinition Height="*"></RowDefinition>  
  9.             <RowDefinition Height="Auto"></RowDefinition>  
  10.         </Grid.RowDefinitions>  
  11.         <local:NavigationPanel Orientation="Horizontal"   
  12.                     x:Name="NavigationPanel"  
  13.                     Height="300"   
  14.                     HorizontalAlignment="Left"  
  15.                     VerticalAlignment="Top">  
  16.               
  17.             <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"  
  18.                   Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"  
  19.                   Background="Blue" >  
  20.                 <TextBlock FontSize="36">Page1</TextBlock>  
  21.             </Grid>  
  22.             <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"  
  23.                   Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"  
  24.                   Background="Violet">  
  25.                 <TextBlock FontSize="36">Page2</TextBlock>  
  26.             </Grid>  
  27.             <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"  
  28.                   Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"  
  29.                   Background="Purple" >  
  30.                 <TextBlock FontSize="36">Page3</TextBlock>  
  31.             </Grid>  
  32.         </local:NavigationPanel>  
  33.           
  34.         <StackPanel Grid.Row="1"  Orientation="Horizontal" >  
  35.             <Button Content="Previous" x:Name="ButtonPreviousPage"  
  36.                     IsEnabled="{Binding ElementName=NavigationPanel, Path=PreviousIsValid, Mode=OneWay}"  
  37.                     Click="ButtonPreviousPage_Click"></Button>  
  38.             <Button Content="Next" x:Name="ButtonNextPage" Click="ButtonNextPage_Click"  
  39.                     IsEnabled="{Binding ElementName=NavigationPanel, Path=NextIsValid, Mode=OneWay}"></Button>           
  40.         </StackPanel>  
  41.     </Grid>  
  42. </Window>  

 

 

C#:

 

 

[csharp] view plaincopy
 
  1. /// <summary>  
  2. /// Interaction logic for MainWindow.xaml  
  3. /// </summary>  
  4. public partial class MainWindow : Window  
  5. {  
  6.     public MainWindow()  
  7.     {  
  8.         InitializeComponent();        
  9.     }  
  10.   
  11.     private void ButtonPreviousPage_Click(object sender, RoutedEventArgs e)  
  12.     {  
  13.         NavigationPanel.Previous();  
  14.     }  
  15.   
  16.   
  17.     private void ButtonNextPage_Click(object sender, RoutedEventArgs e)  
  18.     {  
  19.         NavigationPanel.Next();  
  20.     }  
  21. }  



 

以上是用法,封装的NavigationPanel设计如下:

 

NavigationPanel设计图

 

具体实现如下:

 

 

[csharp] view plaincopy
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Windows;  
  6. using System.Windows.Controls;  
  7. using System.Windows.Data;  
  8. using System.Windows.Documents;  
  9. using System.Windows.Input;  
  10. using System.Windows.Media;  
  11. using System.Windows.Media.Imaging;  
  12. using System.Windows.Navigation;  
  13. using System.Windows.Shapes;  
  14. using System.Windows.Media.Animation;  
  15.   
  16. namespace WPFNavigation  
  17. {  
  18.   
  19.     public class NavigationPanel : StackPanel  
  20.     {  
  21.         public event EventHandler AnimationComplte;  
  22.         private static double COUNT_OF_PAGE;  
  23.         private TranslateTransform NavigationPanelTranslateTransform;  
  24.       
  25.   
  26.         private static readonly TimeSpan DURATION = TimeSpan.FromMilliseconds(250);  
  27.   
  28.         public NavigationPanel():base()  
  29.         {  
  30.             this.Orientation = Orientation.Horizontal;  
  31.               
  32.   
  33.             NavigationPanelTranslateTransform = new TranslateTransform();  
  34.   
  35.             this.Loaded += new RoutedEventHandler(NavigationPanel_Loaded);            
  36.         }  
  37.   
  38.         void NavigationPanel_Loaded(object sender, RoutedEventArgs e)  
  39.         {  
  40.             COUNT_OF_PAGE = this.Children.Count;  
  41.             CurrentIndex = 0;  
  42.             foreach (FrameworkElement fe in this.Children)  
  43.             {  
  44.                 fe.RenderTransform = NavigationPanelTranslateTransform;  
  45.             }  
  46.         }  
  47.   
  48.         public void Next()  
  49.         {  
  50.             AnimationChildren(true);  
  51.         }  
  52.   
  53.         public void Previous()  
  54.         {  
  55.             AnimationChildren(false);  
  56.         }  
  57.   
  58.   
  59.         private bool ValidateNext()  
  60.         {  
  61.             return CurrentIndex < (COUNT_OF_PAGE - 1) && CurrentIndex >= 0;  
  62.         }  
  63.   
  64.   
  65.         private bool ValidatePrevious()  
  66.         {  
  67.             return CurrentIndex <= (COUNT_OF_PAGE - 1) && CurrentIndex > 0;  
  68.         }  
  69.   
  70.         private bool ValidateCurrentIndex()  
  71.         {  
  72.             if (CurrentIndex > -1 && CurrentIndex < this.Children.Count)  
  73.             {  
  74.                 return true;  
  75.             }  
  76.   
  77.             return false;  
  78.         }  
  79.   
  80.         private  void AnimationChildren(bool forward)  
  81.         {  
  82.             double currentTranX = NavigationPanelTranslateTransform.X;  
  83.             double nextTranX = currentTranX;  
  84.             if (forward)  
  85.             {  
  86.                 if (ValidateCurrentIndex())  
  87.                 {  
  88.                     nextTranX -= (this.Children[CurrentIndex] as FrameworkElement).ActualWidth;  
  89.                 }  
  90.                   
  91.             }  
  92.             else  
  93.             {  
  94.                 if (ValidateCurrentIndex())  
  95.                 {  
  96.                     nextTranX += (this.Children[CurrentIndex] as FrameworkElement).ActualWidth;  
  97.                 }  
  98.                   
  99.             }  
  100.   
  101.             DoubleAnimation da = new DoubleAnimation(currentTranX, nextTranX, DURATION);  
  102.             da.Completed += (o1, e1) =>  
  103.             {  
  104.                 CurrentIndex += forward ? 1 : -1;  
  105.                 if (AnimationComplte != null)  
  106.                 {  
  107.                     AnimationComplte(this, e1);  
  108.                 }  
  109.             };  
  110.   
  111.             NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);  
  112.         }  
  113.  
  114.         #region CurrentIndex  
  115.   
  116.         /// <summary>  
  117.         /// The <see cref="CurrentIndex" /> dependency property's name.  
  118.         /// </summary>  
  119.         public const string CurrentIndexPropertyName = "CurrentIndex";  
  120.   
  121.         /// <summary>  
  122.         /// Gets or sets the value of the <see cref="CurrentIndex" />  
  123.         /// property. This is a dependency property.  
  124.         /// </summary>  
  125.         public int CurrentIndex  
  126.         {  
  127.             get  
  128.             {  
  129.                 return (int)GetValue(CurrentIndexProperty);  
  130.             }  
  131.             set  
  132.             {  
  133.                 SetValue(CurrentIndexProperty, value);  
  134.             }  
  135.         }  
  136.   
  137.         /// <summary>  
  138.         /// Identifies the <see cref="CurrentIndex" /> dependency property.  
  139.         /// </summary>  
  140.         public static readonly DependencyProperty CurrentIndexProperty = DependencyProperty.Register(  
  141.             CurrentIndexPropertyName,  
  142.             typeof(int),  
  143.             typeof(NavigationPanel),  
  144.             new UIPropertyMetadata(-1, OnCurrentIndexChanged));  
  145.   
  146.         private static void OnCurrentIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
  147.         {  
  148.             (d as NavigationPanel).OnCurrentIndexChanged((int)e.OldValue, (int)e.NewValue);  
  149.         }  
  150.   
  151.         protected virtual void OnCurrentIndexChanged(int oldIndex, int newIndex)  
  152.         {  
  153.             NextIsValid = ValidateNext();  
  154.             PreviousIsValid = ValidatePrevious();  
  155.         }  
  156.  
  157.         #endregion // CurrentIndex  
  158.  
  159.  
  160.         #region NextIsValid  
  161.   
  162.         /// <summary>  
  163.         /// The <see cref="NextIsValid" /> dependency property's name.  
  164.         /// </summary>  
  165.         public const string NextIsValidPropertyName = "NextIsValid";  
  166.   
  167.         /// <summary>  
  168.         /// Gets or sets the value of the <see cref="NextIsValid" />  
  169.         /// property. This is a dependency property.  
  170.         /// </summary>  
  171.         public bool NextIsValid  
  172.         {  
  173.             get  
  174.             {  
  175.                 return (bool)GetValue(NextIsValidProperty);  
  176.             }  
  177.             set  
  178.             {  
  179.                 SetValue(NextIsValidProperty, value);  
  180.             }  
  181.         }  
  182.   
  183.         /// <summary>  
  184.         /// Identifies the <see cref="NextIsValid" /> dependency property.  
  185.         /// </summary>  
  186.         public static readonly DependencyProperty NextIsValidProperty = DependencyProperty.Register(  
  187.             NextIsValidPropertyName,  
  188.             typeof(bool),  
  189.             typeof(NavigationPanel),  
  190.             new UIPropertyMetadata(false));  
  191.  
  192.         #endregion // NextIsValid  
  193.  
  194.         #region PreviousIsValid  
  195.   
  196.         /// <summary>  
  197.         /// The <see cref="PreviousIsValid" /> dependency property's name.  
  198.         /// </summary>  
  199.         public const string PreviousIsValidPropertyName = "PreviousIsValid";  
  200.   
  201.         /// <summary>  
  202.         /// Gets or sets the value of the <see cref="PreviousIsValid" />  
  203.         /// property. This is a dependency property.  
  204.         /// </summary>  
  205.         public bool PreviousIsValid  
  206.         {  
  207.             get  
  208.             {  
  209.                 return (bool)GetValue(PreviousIsValidProperty);  
  210.             }  
  211.             set  
  212.             {  
  213.                 SetValue(PreviousIsValidProperty, value);  
  214.             }  
  215.         }  
  216.   
  217.         /// <summary>  
  218.         /// Identifies the <see cref="PreviousIsValid" /> dependency property.  
  219.         /// </summary>  
  220.         public static readonly DependencyProperty PreviousIsValidProperty = DependencyProperty.Register(  
  221.             PreviousIsValidPropertyName,  
  222.             typeof(bool),  
  223.             typeof(NavigationPanel),  
  224.             new UIPropertyMetadata(false));  
  225.  
  226.         #endregion // PreviousIsValid  
  227.   
  228.   
  229.   
  230.   
  231.     }  
  232. }