Implementing a Custom Semantic Zoom Container
Implementing a Custom Semantic Zoom Container
Semantic Zoom:
Windows 8 provides a secondary view to view the summary and scroll to the respective section through a container called Semantic zoom. This is functionality is also available at OS level as well as Application level.
There are two Different views:
- Zoomed In View (Details View )(The Default View/ctrl + (scroll mouse up) / pinch out)
- Zoomed Out View(Summary View) (The Summary View/ctrl + (scroll mouse down)/ pinch in)
Default Semantic Zoom Implementation:
The default implementation of semantic zoom is done by implementing the semantic zoom control which has two children the zoomed out view and the zoomed in view. The application switches between the two views with only one of them visible at one point of time.
<SemanticZoom
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch" >
<SemanticZoom.ZoomedOutView>
<!—Your zoomed out view Content inside GridView/ListView-->
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<!—Your zoomed in view Content inside GridView/ListView -->
</SemanticZoom.ZoomedInView>
</SemanticZoom>
Limitation:
The default implementation of Semantic zoom only accepts a GridView / ListView as its child elements. i.e. All the content in your ZoomedInView or ZoomedOutView should be wrapped inside a GridView / ListView.
Problem:
What is the solution if you have to implement a semantic zoom on views with unstructured data or Views that are already implemented using other content controls/panels other than GridView / ListView.
Solution:
The ZoomedInView / ZoomedOutView in a semantic zoom control only accept the children that implement ISemanticZoomInformation interface. The GridView / ListView implement the ISemanticZoomInformation as a part of their implementation. In order to get our panel/container working in a ZoomedInView / ZoomedOutView we can implement a UserControl that inherits from the IsemanticZoomInformation interface.
Below is the code snippet showing implementation of a grid implementing IsemanticZoomInformation.
SemanticZoomGrid.xaml
<Grid
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
</Grid>
SemanticZoomGrid.xaml.cs
public sealed partial class SemanticZoomGrid : Grid, ISemanticZoomInformation
{
public SemanticZoomGrid()
{
this.InitializeComponent();
}
public void CompleteViewChange()
{
}
public void CompleteViewChangeFrom(SemanticZoomLocation source, SemanticZoomLocation destination)
{
}
public void CompleteViewChangeTo(SemanticZoomLocation source, SemanticZoomLocation destination)
{
}
public void InitializeViewChange()
{
}
public bool IsActiveView
{
get;
set;
}
public bool IsZoomedInView
{
get;
set;
}
public void MakeVisible(SemanticZoomLocation item)
{
}
public SemanticZoom SemanticZoomOwner
{
get;
set;
}
public void StartViewChangeFrom(SemanticZoomLocation source, SemanticZoomLocation destination)
{
}
public void StartViewChangeTo(SemanticZoomLocation source, SemanticZoomLocation destination)
{
}
}
The UserControl implemented from the Grid and the IsemanticZoomInformation can now be used in the ZoomedInView and the ZoomedOutView of the semanticzoom control.
Note: if you have a view that goes beyond the screen implement a scroll viewer inside the SemanticZoomGrid user control for the content to scroll properly.
Below is the code snippet implementing the usercontrol in a view
<SemanticZoom ViewChangeStarted="SemanticZoom_ViewChangeStarted">
<SemanticZoom.ZoomedOutView>
<GridView x:Name="groupGridView"
Padding="0,0,10,10"
Margin="116,25,50,0"
Grid.Row="1"
ItemTemplate="{StaticResource ListItemTemplate}"
ItemsSource="{Binding}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Mar-gin="0,0,80,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<userControl:SemanticGrid x:Name="MyCustomSemanticPanel">
<ScrollViewer ZoomMode="Disabled" x:Name="scroller"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled"
VerticalScrollMode="Disabled">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<!--<RowDefinition Height="*"/>-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="A" Grid.Row="0" Grid.Column="0">
<GridView Name="groupGridViewA"
Padding="0,0,10,10"
Margin="116,25,50,0"
ItemTemplate="{StaticResource ListItemTemplate}"
ItemsSource="{Binding}"
Height="800" >
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,10,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</StackPanel>
<StackPanel x:Name="B" Grid.Row="0" Grid.Column="1">
<GridView Name="groupGridViewB"
Padding="0,0,10,10"
Margin="116,25,50,0"
ItemTemplate="{StaticResource ListItemTemplate}"
ItemsSource="{Binding}"
Height="800" >
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</StackPanel>
<StackPanel x:Name="C" Grid.Row="0" Grid.Column="2">
<GridView Name="groupGridViewC"
Padding="0,0,10,10"
Margin="116,25,50,0"
ItemTemplate="{StaticResource ListItemTemplate}"
ItemsSource="{Binding}"
Height="800" >
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</StackPanel>
<StackPanel x:Name="D" Grid.Row="0" Grid.Column="3">
<GridView Name="groupGridViewD"
Padding="0,0,10,10"
Margin="116,25,50,0"
ItemTemplate="{StaticResource ListItemTemplate}"
ItemsSource="{Binding}"
Height="800" >
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</StackPanel>
</Grid>
</ScrollViewer>
</userControl:SemanticGrid>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
Zooming In on to the Correct View:
The Main purpose of the SemanticZoom is to help user reach his data quickly. On click of the summary item the ZomedInView must scroll to the location where user would be interested to see the details. This can be achieved by implementing ViewChangeStarted event of the semanticzoom control.
Code Snippet to implement the zoomin feature:
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomView-ChangedEventArgs e)
{
ScrollViewer fe = (ScrollViewer)MyCustomSemanticPanel.FindName("scroller");
fe.ScrollToHorizontalOffset(0);
if (e.IsSourceZoomedInView)
{
return;
}
else
{
Item i = e.SourceItem.Item as Item;
if (i.Items == "A")
{
StackPanel sp = (StackPanel)MyCustomSemanticPanel.FindName("A");
fe.ScrollToHorizontalOffset(sp.TransformToVisual(fe).TransformBounds(new Rect(0, 0, 1, 1)).Left);
}
else if (i.Items == "B")
{
StackPanel sp = (StackPanel)MyCustomSemanticPanel.FindName("B");
fe.ScrollToHorizontalOffset(sp.TransformToVisual(fe).TransformBounds(new Rect(0, 0, 1, 1)).Left);
}
else if (i.Items == "C")
{
StackPanel sp = (StackPanel)MyCustomSemanticPanel.FindName("C");
fe.ScrollToHorizontalOffset(sp.TransformToVisual(fe).TransformBounds(new Rect(0, 0, 1, 1)).Left);
}
else if (i.Items == "D")
{
StackPanel sp = (StackPanel)MyCustomSemanticPanel.FindName("D");
fe.ScrollToHorizontalOffset(sp.TransformToVisual(fe).TransformBounds(new Rect(0, 0, 1, 1)).Left);
}
}
}
attatched is the SemanticZoom example