How to implement SemanticZoom? - xaml

I have an application that it's main page is organized like this:
Grid (LayoutRoot)
VisualStateManager (FullLandscape, FullPortrait, Filled, Snap)
Grid (Back button and page title)
ScrollViewer (FullLandscape View )
StackPanel (Horizontal)
GridView (non grouped GridView)
GridView (grouped GridView)
GridView (non grouped GridView)
GridView (grouped GridView)
GridView (grouped GridView)
ScrollViewer (Snap View)
Grid
ListView (Vertical)
My questions are:
Do I have to provide a SemanticZoom for each page in my application in order for the application to pass certification?
If I want to provide a SemanticZoom for this main page, how do I do it? i.e. where do I insert the SemanticZoom control?
( I read the article: Quickstart: Adding SemanticZoom controls:)
<SemanticZoom.ZoomedOutView>
<!-- Put the GridView for the zoomed out view here. -->
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<!-- Put the GridView for the zoomed in view here. -->
</SemanticZoom.ZoomedInView>
Thanks,
EitanB

It's a bit hard from to understand what you are trying to achieve from what you have written above, but I'll do my best to answer you questions.
1) SemanticZoom usage is not mandatory to pass certification. It's a nice feature that helps you present data in a neat way to the user and when used appropriately is pretty darn cool.
But, it's just a control. Give us some more information about your project and maybe we can help you decide if it will add something extra or not to the application.
Start easy and work into the details later.
2) Download the SemanticZoom example from MSDN and have a look at the code. BAsically it looks like this:
<Page.Resources>
<CollectionViewSource x:Name="cvs2" IsSourceGrouped="true" />
</Page.Resources>
<Grid x:Name="ContentPanel" VerticalAlignment="Top" HorizontalAlignment="Left">
<SemanticZoom x:Name="semanticZoom" VerticalAlignment="Bottom">
<SemanticZoom.ZoomedOutView>
<GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Group.Key}"
FontFamily="Segoe UI Light"
FontSize="24"/>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid ItemWidth="75" ItemHeight="75" MaximumRowsOrColumns="1" VerticalChildrenAlignment="Center" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="4" />
<Setter Property="Padding" Value="10" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</GridView.ItemContainerStyle>
</GridView>
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<GridView ItemsSource="{Binding Source={StaticResource cvs2}}" IsSwipeEnabled="True" ScrollViewer.IsHorizontalScrollChainingEnabled="False">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0" HorizontalAlignment="Left" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Image Source="{Binding Image}" Height="60" Width="60" VerticalAlignment="Center" Margin="0,0,10,0"/>
<TextBlock TextWrapping="Wrap" Foreground="{StaticResource ApplicationForegroundThemeBrush}" Width="200" VerticalAlignment="Center" Text="{Binding Title}" HorizontalAlignment="Left" FontFamily="Segoe UI" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text='{Binding Key}' Foreground="{StaticResource ApplicationForegroundThemeBrush}" Margin="5" FontSize="18" FontFamily="Segoe UI Light" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.ContainerStyle>
<Style TargetType="GroupItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupItem">
<StackPanel Orientation="Vertical">
<ContentPresenter Content="{TemplateBinding Content}" />
<ItemsControl x:Name="ItemsControl" ItemsSource="{Binding GroupItems}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" MaximumRowsOrColumns="3" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Vertical" MaximumRowsOrColumns="1" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<Button Visibility="Collapsed"/>
</GridView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
</Grid>
and codebehind:
StoreData _storeData = null;
public ScenarioOutput1()
{
InitializeComponent();
_storeData = new StoreData();
List<GroupInfoList<object>> dataCategory = _storeData.GetGroupsByCategory();
cvs1.Source = dataCategory;
}

Thanks for your answer.
I did see the example and it is clear to me. What is not clear to me is: I have on this one page multiple GridViews not just one like in the example. The question that is open in my mind is: Should I follow the example code for each of the GridViews on the page, or is there a way to do it once for the page that will cover all GridViews? Please see the pseudo code below.
Thanks,
EitanB
VisualStateManager (FullLandscape, FullPortrait, Filled, Snap)
Grid (Back button and page title)
ScrollViewer (FullLandscape View )
StackPanel (Horizontal)
<SemanticZoom x:Name="semanticZoom1" VerticalAlignment="Bottom">
<SemanticZoom.ZoomedOutView>
GridView (non grouped GridView)
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
GridView (non grouped GridView - Semantic Version)
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<SemanticZoom x:Name="semanticZoom2" VerticalAlignment="Bottom">
<SemanticZoom.ZoomedOutView>
GridView (grouped GridView)
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
GridView (grouped GridView - Semantic Version)
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<SemanticZoom x:Name="semanticZoom3" VerticalAlignment="Bottom">
<SemanticZoom.ZoomedOutView>
GridView (non grouped GridView)
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
GridView (non grouped GridView - Semantic Version)
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<SemanticZoom x:Name="semanticZoom4" VerticalAlignment="Bottom">
<SemanticZoom.ZoomedOutView>
GridView (grouped GridView)
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
GridView (grouped GridView - Semantic Version)
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<SemanticZoom x:Name="semanticZoom5" VerticalAlignment="Bottom">
<SemanticZoom.ZoomedOutView>
GridView (grouped GridView)
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
GridView (grouped GridView - Semantic Version)
</SemanticZoom.ZoomedInView>
</SemanticZoom>
ScrollViewer (Snap View)
Grid
ListView (Vertical)

The way to do it is like I posted in my question, i.e. the question was asking if it is the right way and the answer is yes.
EitanB

Related

Independent scrolling of StackPanels in grouped ListView

I currently have the following XAML for a ListView, and I want the individual panels to scroll vertically and independently of each other.
Currently, when I use the scrolling function in the stack panel, panel 1, 2 and 3 all scroll vertically together. Importantly, I do not know how many panels there will be, sometimes there will be one, and on another day there could be six.
I would like for the panels to scroll vertically and independently of the other panels.
The thing I am struggling to achieve is to make the <ListView.ItemsPanel> dynamic enough to create individual stack panels, based on the groups in the data. I assume this will make the <GroupStyle.Panel> work independently.
I thought that the <ItemsPanelTemplate> would treat them as individuals and not as a whole group.
The XAML I currently have is as follows:
<ListView Grid.Column="1" Grid.Row="0" Grid.RowSpan="2"
ItemsSource="{Binding Source={StaticResource SomeData Mode=OneWay}"
ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollMode="Enabled">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Width="150">
<TextBlock Text="{Binding Title, TargetNullValue='No Data'}"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<StackPanel ScrollViewer.VerticalScrollMode="Enabled" Orientation="Vertical" Spacing="4"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="GroupItem">
<Setter Property="Background" Value="Gray" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="4" />
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
</ListView>

WrapPanel inside ListBox in UWP

I am looking to add WrapPanel inside my ListBox so that it's item wrap both vertically and horizentally. I was able to achieve this in Windows Phone 8 Sliverlight with Microsoft toolkit with below code;
Windows Phone 8
<ListBox x:Name="ListSection" ItemsSource="{Binding Section}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" ></toolkit:WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="20">
<Image Source="{Binding ImagePath}" Width="80" Height="80"></Image>
<TextBlock Style="{StaticResource PhoneTextBlockBase}"
HorizontalAlignment="Center"
Foreground="Black"
Text="{Binding Header}"
FontWeight="Bold"
VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
I understand that Microsoft toolkit it not available in UWP, is there any possibility I could achieve such behavior in UWP?
UWP not working
<ListBox x:Name="ItemsListBox" ItemsSource="{Binding Section}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel HorizontalAlignment="Stretch"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding ImagePath}" Width="80" Height="80"></Image>
<TextBlock HorizontalAlignment="Center"
Foreground="Black"
Text="{Binding Header}"
FontWeight="Bold"
VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Thanks!
You must use ListView and ItemsWrapGrid as ItemsPanel
you can check the MSDN docs here with examples
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemswrapgrid.aspx
This example is for GridView but is the same for ListView
<GridView>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
you can use the property Orientation to set your items vertically or horizontally.
There is a port of the Toolkit's WrapPanel for UWP in the project WinRTXamlToolkit.
You can get it from NuGet.
Then in your Page add this prefix:
xmlns:toolkit="using:WinRTXamlToolkit.Controls"
Now you can use <toolkit:WrapPanel Orientation="Horizontal" ></toolkit:WrapPanel> as it was before.
#ARH you need to create a custom Panel class which inherits panel class and override MeasureOverride and ArrangeOverride methods.check out following links for reference.
https://msdn.microsoft.com/en-us/library/windows/apps/mt228347.aspx
http://www.visuallylocated.com/post/2015/02/20/Creating-a-WrapPanel-for-your-Windows-Runtime-apps.aspx
The WrapPanel is available from the Microsoft UWP Toolkit.
Here's some sample code (using v5.0.0):
...
xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"
...
<ListView
Name="WrapPanelContainer"
Width="310" Height="200"
Margin="0,40,0,0"
HorizontalAlignment="Left"
Background="LightBlue"
IsItemClickEnabled="True"
>
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListView.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel VerticalSpacing="10" HorizontalSpacing="10" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<Rectangle Fill="Red" Width="100" Height="50"/>
<Rectangle Fill="Blue" Width="200" Height="50"/>
<Rectangle Fill="Green" Width="50" Height="50"/>
<Rectangle Fill="Yellow" Width="150" Height="50"/>
</ListView>
NOTE: The ListItemView style here removes superfluous padding, allowing the WrapPanel spacing properties to be the control points for layout.

ListView ItemTemplate Grid 100% Width

I have made an ListView ItemTemplate and I want it to be responsive (when orientation changes, for example, the listView item changes in size). I am using a Grid as a control for the inner elements of the grid but it is not behaving. The ListView.ItemContainerStyle has property HorizontalAlignment="Stretch" which is the behaviour I want, and the ItemContainerStyle is the correct width. Inside the Border and Grid I have the same HorizontalAlignment="Stretch" and they are overflowing when the TextBox contained inside has lots of text, and when there is little or no text in the TextBox the Border element shrinks to be smaller than the ItemContainerStyle is showing.
<ListView ItemsSource="{Binding TileStories}" x:Name="cont" Margin="0,10,0,10" Background="{StaticResource CustomResourceBrush}" BorderBrush="{StaticResource CustomResourceBrush}" Foreground="{StaticResource CustomResourceBrush}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="20,10,20,10" />
<Setter Property="Foreground" Value="{StaticResource BTVioletBrush}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border CornerRadius="20" BorderThickness="0" Width="{Binding ScrollViewerWidth}" Background="White" HorizontalAlignment="Stretch">
<StackPanel Height="160" Orientation="Horizontal">
<Grid Background="black">
<TextBox Text="Example">
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Just do this
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
Define MinHeight as 0 for ItemContainerStyle
Add to your ItemContainerStyle
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
And I think Width="{Binding ScrollViewerWidth}" is not required. You can remove this.
I didn't exactly find a solution but I did find a workaround. The Grid was being bound with Width="0" if I used {Binding ActualWidth, ElementName=StackPanel, Mode=OneWay} where StackPanel was the panel within the data template. I was poking around the designer in VS2013 and figured out that the Width was 0 because (I am assuming) the items in the data template are drawn one by one and therefore the Width was zero when the first template was drawn and so on and so forth. I haven't explained that very well I guess, but the important thing is the solution:
<PivotItem x:Name="Feed">
....
<Border CornerRadius="20" BorderThickness="0" Background="White" HorizontalAlignment="Stretch">
<StackPanel Height="160" Orientation="Horizontal">
<Grid HorizontalAlignment="Stretch" Width="{Binding ActualWidth, ElementName=Feed, Mode=OneWay}">
........
</Grid>
</StackPanel>
</Border>
...
</PivotItem>
I think that the PivotItem having a non-variable Width meant the Grid had a concrete Width to inherit from.

Stretch Items in an ItemsControl in XAML

SOLUTION
The shortest Code to archieve the desired result was for me:
<ItemsControl ItemsSource="{Binding GeneralBoolSettings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<ToggleSwitch IsOn="{Binding IsOn, Mode=TwoWay}" OffContent="{Binding OffContent}" OnContent="{Binding OnContent}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
ORIGINAL QUESTION
I'm having trouble with something as easy as stretching the Items of an ItemControl horizontally. As I'm working with XAML, I dont have things like SharedSizeGroupas in WPF.
The solutioon presented here: Horizontally Stretch Content in an ItemsControl does unfortunately not work for me.
My Code:
<ItemsControl ItemsSource="{Binding GeneralBoolSettings}" HorizontalContentAlignment="Stretch">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<ToggleSwitch IsOn="{Binding IsOn, Mode=TwoWay}" OffContent="{Binding OffContent}" OnContent="{Binding OnContent}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Some Screenshots from the Designer:
ItemControl has the correct (stretched) Size
DataTemplate is already too small
I would like to avoid binding to a parent width; in my previous attempts, the width was sometimes (re-)set to 0, and I would have had to remove the binding and add it again. Also: Please no code and / or event catcher, there must be an elegant solution to this rather basic problem!
Honestly, I'm a bit surprised I can't get this to work. Mabye you can recommend a good book / website to learn a systematic approach of the basics of XAML (while we're at it)?
You also need to set the horizontal alignment of each item container to stretch using ItemContainerStyle property of ItemsControl.
<ItemsControl ItemsSource="{Binding GeneralBoolSettings}" HorizontalContentAlignment="Stretch">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<ToggleSwitch IsOn="{Binding IsOn, Mode=TwoWay}" OffContent="{Binding OffContent}" OnContent="{Binding OnContent}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>

item orientation in wrapgrid in windows8

I use a wrapgrid as the itemspaneltemplate in my app
<GridView x:Name="InfoGridView" Margin="50">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Vertical" ItemWidth="200" ItemHeight="50" Height="400" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<TextBlock Text="Name" Style="{StaticResource AppNameTextStyle}" />
<TextBox x:Name="NameTextBox" Width="180"/>
<Button x:Name="AnotherNameButton" Style="{StaticResource AddAppBarButtonStyle}"/>
</GridView>
The TextBlock, TextBox and the Button are display in the middle of the item, how to let them display keep left?
Set this up on the ItemContainerStyle within your GridView by adding the following XAML below your ItemsPanel entry.
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</GridView.ItemContainerStyle>