Jak poprawić scroll’a w Semantic Zoom (zoom out)

Zapewne każdy WinRT Developer wie czym jest Semantic Zoom.

Semantic zoom - widok normalny (zoom-in)

Semantic zoom – widok normalny (zoom-in)

Semantic zoom - widok oddalony, zgrupowany (zoom-out)

Semantic zoom – widok oddalony, zgrupowany (zoom-out)

A jak nie wie to odsyłam do poczytania albo do pooglądania.

W czym problem?

Problem z jakim ja się spotkałem to nieprawidłowe zachowanie się Semantic Zoom scroll’a w stanie zoomed out. Jest to problem wyłącznie UI.

Gdy content, który chcę wyświetlić nie mieści się na szerokość, wówczas będzie on automatycznie przewijany horyzontalnie. Gdy dotrzemy do końca (lub początku) treści i nadal przesuwamy zawartość to cała kontrolka (w tym przypadku Grid) zostanie przesunięty i pojawi się tło pod nim.

Semantic zoom - widok zoomed-out (nieprawidłowy)

Semantic zoom – widok zoomed-out (nieprawidłowy)

Przesuwa się cały Grid: zarówno nagłowek (TextBlock) jak i treść (GridView). A przecierz lepiej by to wyglądało gdyby nagłówek był zablokowany, a jedynie treść (te duże kafelki) lekko przesunęła się.

Semantic zoom - poprawiony

Semantic zoom – poprawiony

Czyli dokładnie tak samo jak Start w Windows 8, czy większość aplikacji Windows 8 ze sklepu.

Rozwiązanie

Aby rozwiązać problem należy zmienić domyślny styl kontrolki Semantic Zoom. W tym celu użyj gotowego kawałka kodu XAML. Skopiuj go do siebie do App.xaml lub do strony na której używasz Semantic Zoom lub w inne miejsce gdzie trzymasz style:

<Style TargetType="SemanticZoom">
<Setter Property="Padding" Value="3"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled"/>
<Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled"/>
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="SemanticZoom">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SemanticZoomStates">
<VisualState x:Name="ZoomInView">
<Storyboard>
<FadeOutThemeAnimation TargetName="ZoomedOutPresenter"/>
<FadeInThemeAnimation TargetName="ZoomedInPresenter"/>
</Storyboard>
</VisualState>
<VisualState x:Name="ZoomOutView">
<Storyboard>
<FadeOutThemeAnimation TargetName="ZoomedInPresenter"/>
<FadeInThemeAnimation TargetName="ZoomedOutPresenter"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ZoomOutButtonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="ZoomOutButtonVisible" To="ZoomOutButtonHidden">
<Storyboard BeginTime="0:0:3">
<FadeOutThemeAnimation TargetName="ZoomOutButton"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="ZoomOutButton">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Boolean>False</x:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="ZoomOutButtonVisible">
<Storyboard>
<FadeInThemeAnimation TargetName="ZoomOutButton"/>
</Storyboard>
</VisualState>
<VisualState x:Name="ZoomOutButtonHidden">
<Storyboard>
<FadeOutThemeAnimation TargetName="ZoomOutButton"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="ZoomOutButton">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Boolean>False</x:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollMode="Disabled" HorizontalContentAlignment="Center" HorizontalScrollBarVisibility="Hidden" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsScrollInertiaEnabled="True" IsZoomChainingEnabled="True" IsZoomInertiaEnabled="False" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" MinZoomFactor="0.5" MaxZoomFactor="1.0" VerticalScrollBarVisibility="Hidden" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" VerticalContentAlignment="Center" ZoomMode="Enabled">
<ScrollViewer.Template>
<ControlTemplate TargetType="ScrollViewer">
<ScrollContentPresenter x:Name="ScrollContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Margin="{TemplateBinding Padding}"/>
</ControlTemplate>
</ScrollViewer.Template>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderTransformOrigin="0, 0">
<Border.RenderTransform>
<CompositeTransform x:Name="ManipulatedElementTransform"/>
</Border.RenderTransform>
<Grid Margin="{TemplateBinding Padding}">
<ContentPresenter x:Name="ZoomedInPresenter" Content="{TemplateBinding ZoomedInView}" IsHitTestVisible="False" RenderTransformOrigin="0.5, 0.5" Visibility="Collapsed">
<ContentPresenter.RenderTransform>
<CompositeTransform x:Name="ZoomedInTransform"/>
</ContentPresenter.RenderTransform>
</ContentPresenter>
<ContentPresenter x:Name="ZoomedOutPresenter" Content="{TemplateBinding ZoomedOutView}" IsHitTestVisible="False" RenderTransformOrigin="0.5, 0.5" Visibility="Collapsed">
<ContentPresenter.RenderTransform>
<CompositeTransform x:Name="ZoomedOutTransform"/>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Grid>
</Border>
</ScrollViewer>
<Button x:Name="ZoomOutButton" HorizontalAlignment="Right" IsTabStop="False" Margin="0,0,7,24" VerticalAlignment="Bottom">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="Root" BorderBrush="{StaticResource SemanticZoomButtonBorderThemeBrush}" BorderThickness="1" Background="{StaticResource SemanticZoomButtonBackgroundThemeBrush}" Height="21" Width="21">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="NormalStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Root">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SemanticZoomButtonPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Root">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SemanticZoomButtonPointerOverBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Glyph">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SemanticZoomButtonPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Root">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SemanticZoomButtonPressedBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Root">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SemanticZoomButtonPressedBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Glyph">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SemanticZoomButtonPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="Glyph" Foreground="{StaticResource SemanticZoomButtonForegroundThemeBrush}" FontSize="{StaticResource SemanticZoomButtonFontSize}" FontFamily="{StaticResource SymbolThemeFontFamily}" HorizontalAlignment="Center" IsHitTestVisible="False" Margin="0,0,0,1" Text="" UseLayoutRounding="False" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>