WPF如何实现类似iPhone界面切换的效果 (version .1)
转自:http://blog.csdn.net/fallincloud/article/details/6968764
在论坛上见到有人提出了这个问题(WPF实现点击横向切换界面)
我简单地做了个Sample。
效果图1:
效果图2:
设计思路
将这多个界面放入一个Orientation为Horizontal的StackPanel当中,点击Next时,里面所有控件执行TranslteTransform动画。
实现
xaml
- <Windowx:Class="WPFNavigation.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="MainWindow"Height="350"Width="400">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinitionHeight="*"></RowDefinition>
- <RowDefinitionHeight="Auto"></RowDefinition>
- </Grid.RowDefinitions>
- <StackPanelOrientation="Horizontal"
- x:Name="NavigationPanel"
- Height="300"
- HorizontalAlignment="Left"
- VerticalAlignment="Top">
- <GridWidth="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeWindow}},Path=ActualWidth}"
- Height="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeStackPanel}},Path=ActualHeight}"
- Background="Blue">
- <TextBlockFontSize="36">Page1</TextBlock>
- </Grid>
- <GridWidth="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeWindow}},Path=ActualWidth}"
- Height="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeStackPanel}},Path=ActualHeight}"
- Background="Violet">
- <TextBlockFontSize="36">Page2</TextBlock>
- </Grid>
- <GridWidth="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeWindow}},Path=ActualWidth}"
- Height="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeStackPanel}},Path=ActualHeight}"
- Background="Purple">
- <TextBlockFontSize="36">Page3</TextBlock>
- </Grid>
- </StackPanel>
- <StackPanelGrid.Row="1"Orientation="Horizontal">
- <ButtonContent="Previous"x:Name="ButtonPreviousPage"Click="ButtonPreviousPage_Click"></Button>
- <ButtonContent="Next"x:Name="ButtonNextPage"Click="ButtonNextPage_Click"></Button>
- </StackPanel>
- </Grid>
- </Window>
cs中
- ///<summary>
- ///InteractionlogicforMainWindow.xaml
- ///</summary>
- publicpartialclassMainWindow:Window
- {
- privatestaticreadonlydoubleCOUNT_PAGE=3;
- privateTranslateTransformNavigationPanelTranslateTransform;
- publicMainWindow()
- {
- InitializeComponent();
- NavigationPanelTranslateTransform=newTranslateTransform();
- this.Loaded+=newRoutedEventHandler(MainWindow_Loaded);
- }
- voidMainWindow_Loaded(objectsender,RoutedEventArgse)
- {
- foreach(FrameworkElementfeinNavigationPanel.Children)
- {
- fe.RenderTransform=NavigationPanelTranslateTransform;
- }
- DeterminButtonStates();
- }
- privatevoidDeterminButtonStates()
- {
- doublecurrentTranX=NavigationPanelTranslateTransform.X;
- if(currentTranX>=0)
- {
- ButtonPreviousPage.IsEnabled=false;
- }
- elseif(currentTranX<=-(COUNT_PAGE-1)*this.ActualWidth)
- {
- ButtonNextPage.IsEnabled=false;
- }
- else
- {
- ButtonPreviousPage.IsEnabled=true;
- ButtonNextPage.IsEnabled=true;
- }
- }
- privatevoidButtonPreviousPage_Click(objectsender,RoutedEventArgse)
- {
- doublecurrentTranX=NavigationPanelTranslateTransform.X;
- DoubleAnimationda=newDoubleAnimation(currentTranX,currentTranX+this.ActualWidth,TimeSpan.FromMilliseconds(250));
- da.Completed+=(o1,e1)=>
- {
- DeterminButtonStates();
- };
- NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty,da);
- }
- privatevoidButtonNextPage_Click(objectsender,RoutedEventArgse)
- {
- doublecurrentTranX=NavigationPanelTranslateTransform.X;
- DoubleAnimationda=newDoubleAnimation(currentTranX,currentTranX-this.ActualWidth,TimeSpan.FromMilliseconds(250));
- da.Completed+=(o1,e1)=>
- {
- DeterminButtonStates();
- };
- NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty,da);
- }
- }
WPF如何实现类似iPhone界面切换的效果 (version .2)
转自:http://blog.csdn.net/fallincloud/article/details/6969329
前面写了篇WPF如何实现类似iPhone界面切换的效果 (version .1)
现在又花了点时间重构了下,将动画的效果和Previous和Next这两个按钮的状态控制都封装了起来,效果依然和前面一样
不过重用性高了许多。使用方法如下:
XAML:
- <Windowx:Class="WPFNavigation.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="clr-namespace:WPFNavigation"
- Title="MainWindow"Height="350"Width="400">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinitionHeight="*"></RowDefinition>
- <RowDefinitionHeight="Auto"></RowDefinition>
- </Grid.RowDefinitions>
- <local:NavigationPanelOrientation="Horizontal"
- x:Name="NavigationPanel"
- Height="300"
- HorizontalAlignment="Left"
- VerticalAlignment="Top">
- <GridWidth="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeWindow}},Path=ActualWidth}"
- Height="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:Typelocal:NavigationPanel}},Path=ActualHeight}"
- Background="Blue">
- <TextBlockFontSize="36">Page1</TextBlock>
- </Grid>
- <GridWidth="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeWindow}},Path=ActualWidth}"
- Height="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:Typelocal:NavigationPanel}},Path=ActualHeight}"
- Background="Violet">
- <TextBlockFontSize="36">Page2</TextBlock>
- </Grid>
- <GridWidth="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:TypeWindow}},Path=ActualWidth}"
- Height="{BindingRelativeSource={RelativeSourceMode=FindAncestor,AncestorLevel=1,AncestorType={x:Typelocal:NavigationPanel}},Path=ActualHeight}"
- Background="Purple">
- <TextBlockFontSize="36">Page3</TextBlock>
- </Grid>
- </local:NavigationPanel>
- <StackPanelGrid.Row="1"Orientation="Horizontal">
- <ButtonContent="Previous"x:Name="ButtonPreviousPage"
- IsEnabled="{BindingElementName=NavigationPanel,Path=PreviousIsValid,Mode=OneWay}"
- Click="ButtonPreviousPage_Click"></Button>
- <ButtonContent="Next"x:Name="ButtonNextPage"Click="ButtonNextPage_Click"
- IsEnabled="{BindingElementName=NavigationPanel,Path=NextIsValid,Mode=OneWay}"></Button>
- </StackPanel>
- </Grid>
- </Window>
C#:
- ///<summary>
- ///InteractionlogicforMainWindow.xaml
- ///</summary>
- publicpartialclassMainWindow:Window
- {
- publicMainWindow()
- {
- InitializeComponent();
- }
- privatevoidButtonPreviousPage_Click(objectsender,RoutedEventArgse)
- {
- NavigationPanel.Previous();
- }
- privatevoidButtonNextPage_Click(objectsender,RoutedEventArgse)
- {
- NavigationPanel.Next();
- }
- }
以上是用法,封装的NavigationPanel设计如下:
具体实现如下:
- usingSystem;
- usingSystem.Collections.Generic;
- usingSystem.Linq;
- usingSystem.Text;
- usingSystem.Windows;
- usingSystem.Windows.Controls;
- usingSystem.Windows.Data;
- usingSystem.Windows.Documents;
- usingSystem.Windows.Input;
- usingSystem.Windows.Media;
- usingSystem.Windows.Media.Imaging;
- usingSystem.Windows.Navigation;
- usingSystem.Windows.Shapes;
- usingSystem.Windows.Media.Animation;
- namespaceWPFNavigation
- {
- publicclassNavigationPanel:StackPanel
- {
- publiceventEventHandlerAnimationComplte;
- privatestaticdoubleCOUNT_OF_PAGE;
- privateTranslateTransformNavigationPanelTranslateTransform;
- privatestaticreadonlyTimeSpanDURATION=TimeSpan.FromMilliseconds(250);
- publicNavigationPanel():base()
- {
- this.Orientation=Orientation.Horizontal;
- NavigationPanelTranslateTransform=newTranslateTransform();
- this.Loaded+=newRoutedEventHandler(NavigationPanel_Loaded);
- }
- voidNavigationPanel_Loaded(objectsender,RoutedEventArgse)
- {
- COUNT_OF_PAGE=this.Children.Count;
- CurrentIndex=0;
- foreach(FrameworkElementfeinthis.Children)
- {
- fe.RenderTransform=NavigationPanelTranslateTransform;
- }
- }
- publicvoidNext()
- {
- AnimationChildren(true);
- }
- publicvoidPrevious()
- {
- AnimationChildren(false);
- }
- privateboolValidateNext()
- {
- returnCurrentIndex<(COUNT_OF_PAGE-1)&&CurrentIndex>=0;
- }
- privateboolValidatePrevious()
- {
- returnCurrentIndex<=(COUNT_OF_PAGE-1)&&CurrentIndex>0;
- }
- privateboolValidateCurrentIndex()
- {
- if(CurrentIndex>-1&&CurrentIndex<this.Children.Count)
- {
- returntrue;
- }
- returnfalse;
- }
- privatevoidAnimationChildren(boolforward)
- {
- doublecurrentTranX=NavigationPanelTranslateTransform.X;
- doublenextTranX=currentTranX;
- if(forward)
- {
- if(ValidateCurrentIndex())
- {
- nextTranX-=(this.Children[CurrentIndex]asFrameworkElement).ActualWidth;
- }
- }
- else
- {
- if(ValidateCurrentIndex())
- {
- nextTranX+=(this.Children[CurrentIndex]asFrameworkElement).ActualWidth;
- }
- }
- DoubleAnimationda=newDoubleAnimation(currentTranX,nextTranX,DURATION);
- da.Completed+=(o1,e1)=>
- {
- CurrentIndex+=forward?1:-1;
- if(AnimationComplte!=null)
- {
- AnimationComplte(this,e1);
- }
- };
- NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty,da);
- }
- #regionCurrentIndex
- ///<summary>
- ///The<seecref="CurrentIndex"/>dependencyproperty'sname.
- ///</summary>
- publicconststringCurrentIndexPropertyName="CurrentIndex";
- ///<summary>
- ///Getsorsetsthevalueofthe<seecref="CurrentIndex"/>
- ///property.Thisisadependencyproperty.
- ///</summary>
- publicintCurrentIndex
- {
- get
- {
- return(int)GetValue(CurrentIndexProperty);
- }
- set
- {
- SetValue(CurrentIndexProperty,value);
- }
- }
- ///<summary>
- ///Identifiesthe<seecref="CurrentIndex"/>dependencyproperty.
- ///</summary>
- publicstaticreadonlyDependencyPropertyCurrentIndexProperty=DependencyProperty.Register(
- CurrentIndexPropertyName,
- typeof(int),
- typeof(NavigationPanel),
- newUIPropertyMetadata(-1,OnCurrentIndexChanged));
- privatestaticvoidOnCurrentIndexChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
- {
- (dasNavigationPanel).OnCurrentIndexChanged((int)e.OldValue,(int)e.NewValue);
- }
- protectedvirtualvoidOnCurrentIndexChanged(intoldIndex,intnewIndex)
- {
- NextIsValid=ValidateNext();
- PreviousIsValid=ValidatePrevious();
- }
- #endregion//CurrentIndex
- #regionNextIsValid
- ///<summary>
- ///The<seecref="NextIsValid"/>dependencyproperty'sname.
- ///</summary>
- publicconststringNextIsValidPropertyName="NextIsValid";
- ///<summary>
- ///Getsorsetsthevalueofthe<seecref="NextIsValid"/>
- ///property.Thisisadependencyproperty.
- ///</summary>
- publicboolNextIsValid
- {
- get
- {
- return(bool)GetValue(NextIsValidProperty);
- }
- set
- {
- SetValue(NextIsValidProperty,value);
- }
- }
- ///<summary>
- ///Identifiesthe<seecref="NextIsValid"/>dependencyproperty.
- ///</summary>
- publicstaticreadonlyDependencyPropertyNextIsValidProperty=DependencyProperty.Register(
- NextIsValidPropertyName,
- typeof(bool),
- typeof(NavigationPanel),
- newUIPropertyMetadata(false));
- #endregion//NextIsValid
- #regionPreviousIsValid
- ///<summary>
- ///The<seecref="PreviousIsValid"/>dependencyproperty'sname.
- ///</summary>
- publicconststringPreviousIsValidPropertyName="PreviousIsValid";
- ///<summary>
- ///Getsorsetsthevalueofthe<seecref="PreviousIsValid"/>
- ///property.Thisisadependencyproperty.
- ///</summary>
- publicboolPreviousIsValid
- {
- get
- {
- return(bool)GetValue(PreviousIsValidProperty);
- }
- set
- {
- SetValue(PreviousIsValidProperty,value);
- }
- }
- ///<summary>
- ///Identifiesthe<seecref="PreviousIsValid"/>dependencyproperty.
- ///</summary>
- publicstaticreadonlyDependencyPropertyPreviousIsValidProperty=DependencyProperty.Register(
- PreviousIsValidPropertyName,
- typeof(bool),
- typeof(NavigationPanel),
- newUIPropertyMetadata(false));
- #endregion//PreviousIsValid
- }
- }