Стандартный элемент управления FlipControl (от слова flip - переворачивать) имеет переднюю и заднюю часть для содержания контента и может переворачиваться от одного вида к другому. Как правило реализация подобного элемента управления сводится к созданию 2-х свойств зависимостей: FronContent и BackContent. И соответственно в качестве контента устанавливается нужный вам элемент. Я же решил пойти дальше и не ограничивать себя количеством элементов, которые может содержать FlipControl. Вот что получилось:
FlipControl.cs:
#region DependencyProperty Members /// <summary> /// Using a DependencyProperty as the backing store for front content. /// </summary> public static readonly DependencyProperty FirstContentProperty = DependencyProperty.Register("FirstContent", typeof(Object), typeof(FlipControl), new PropertyMetadata(null)); /// <summary> /// /// </summary> public Object FirstContent { get { return GetValue(FirstContentProperty); } private set { SetValue(FirstContentProperty, value); } } /// <summary> /// Using a DependencyProperty as the backing store for back content. /// </summary> public static readonly DependencyProperty SecondContentProperty = DependencyProperty.Register("SecondContent", typeof(Object), typeof(FlipControl), new PropertyMetadata(null)); /// <summary> /// /// </summary> public Object SecondContent { get { return GetValue(SecondContentProperty); } private set { SetValue(SecondContentProperty, value); } } /// <summary> /// Using a DependencyProperty as the current index of content. /// </summary> public static readonly DependencyProperty CurrentIndexProperty = DependencyProperty.Register("CurrentIndex", typeof(Int32), typeof(FlipControl), new PropertyMetadata(0, CurrentIndexChangedCallback)); /// <summary> /// /// </summary> public Int32 CurrentIndex { get { return (Int32)GetValue(CurrentIndexProperty); } set { SetValue(CurrentIndexProperty, value); } } /// <summary> /// /// </summary> /// <param name="target"></param> /// <param name="args"></param> private static void CurrentIndexChangedCallback(DependencyObject target, DependencyPropertyChangedEventArgs args) { var flipControl = target as FlipControl; if (flipControl == null) return; flipControl.FlipTo((Int32)args.NewValue); } #endregion
Так же как и везде - FirstContent, SecondContent (оба свойства только для чтения) + CurrentIndex (для хранения индекса текущего элемента из коллекции ItemsSource). И как видно при изменении индекса элемент управления "переворачивается" на нужный контент:
FlipControl.cs:
#region Private Members /// <summary> /// /// </summary> /// <param name="index"></param> private void FlipTo(Int32 index) { if (CurrentIndex == oldIndex) return; if (index < 0 || index >= Items.Count) return; oldIndex = CurrentIndex; if (flag) { flag = false; SecondContent = Items[CurrentIndex]; VisualStateManager.GoToState(this, "FirstState", true); } else { flag = true; FirstContent = Items[CurrentIndex]; VisualStateManager.GoToState(this, "SecondState", true); } } #endregion
Осталось теперь только глянуть на XAML-разметку и убедиться, что VisualStateManager имеет нужные VisualState:
Theme.xaml:
<Style TargetType="local:FlipControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:FlipControl"> <Grid x:Name="PART_Root"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="VisualStateGroup"> <VisualState x:Name="DefaultState"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="GridFront"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="GridBack"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="FirstState"> <Storyboard > <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridBack"> <SplineDoubleKeyFrame KeyTime="0" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="GridBack"> <SplineDoubleKeyFrame KeyTime="0" Value="1"/> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="GridBack"> <DiscreteObjectKeyFrame KeyTime="0:0:0.2"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridFront"> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="GridFront"> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="GridFront"> <DiscreteObjectKeyFrame KeyTime="0:0:0.2"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="SecondState"> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridBack"> <SplineDoubleKeyFrame KeyTime="0" Value="1"/> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="GridBack"> <SplineDoubleKeyFrame KeyTime="0" Value="1"/> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="GridBack"> <DiscreteObjectKeyFrame KeyTime="0:0:0.2"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridFront"> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="GridFront"> <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="GridFront"> <DiscreteObjectKeyFrame KeyTime="0:0:0.2"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid x:Name="GridFront" RenderTransformOrigin="0.5,0.5"> <Grid.RenderTransform> <CompositeTransform/> </Grid.RenderTransform> <ContentPresenter x:Name="PART_Front" Content="{TemplateBinding FirstContent}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> </Grid> <Grid x:Name="GridBack" RenderTransformOrigin="0.5,0.5"> <Grid.RenderTransform> <CompositeTransform/> </Grid.RenderTransform> <ContentPresenter x:Name="PART_Back" Content="{TemplateBinding SecondContent}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> </Grid> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
А в качестве идей для развития можно реализовать различные эффекты при "переворачивании" с контента на контент.
Комментариев нет:
Отправить комментарий