Im working on building different layouts for my app. If the app runs in landscape I want to be able to show a map on one side on the screen, but not show a map if in portrait. I'm using VisualStateManager to help me do this.
I need to run some code in c# on the map control I have named "MyMap" but how can I make that bit of the code run only when the map is present - in other words is there a way I can check if it exists in the XAML?
Without the map any code referring to MyMap of course throws an error - is this the best way of going about this or am I missing a better way?
EDIT
I'm using an approach similar to the below to work out what template should be used depending on the MinWindowWidth. So MyMap will only exist in the LargeTemplate etc
<Page.Resources>
<DataTemplate x:Key="SmallTemplate">
<Grid>
<Border Background="LightGray" Height="100" Width="100">
<TextBlock Text="{Binding Text}"
FontSize="48" Foreground="Green" />
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="LargeTemplate">
<Grid>
<Border Background="LightGray" Height="200" Width="200">
<TextBlock Text="{Binding Text}"
FontSize="48" Foreground="Green" />
</Border>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Small">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MyGridView.ItemTemplate" Value="{StaticResource SmallTemplate}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Large">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MyGridView.ItemTemplate" Value="{StaticResource LargeTemplate}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<GridView Name="MyGridView"/>
</Grid>
Add an x:Name to your VisualStateGroup eg. AdaptiveVisualStateGroup, after that you can check for the CurrentState in your code like this:
AdaptiveVisualStateGroup.CurrentState
If the CurrentState equals Large or whatever the name is your VisualState where you have your map, you can run the code that references MyMap, otherwise you just skip it
Related
I'm trying to bind my icon to a property in my appshell viewmodel. This works for the first time, and I am watching the "flyoutispresented" property change to update the icon - I'm switching between two different png's. The event fires every time, and I can see the property in the viewmodel is updating, but the flyout image is not changing. It seems to stay the way it was when first rendered. In my appshell constructor, I am doing the following:
model = new AppShellViewModel();
this.BindingContext = model;
this.PropertyChanged +=
(obj, args) => model.Shell_PropertyChanged(obj, args);
so I am using the single instance of the view model, and that method is being called properly. Has anyone had luck displaying different icons like this? What am I missing that even though I'm changing the icon property, it's not showing the change?
We could modefy the icon source via VisualStateManager status selected and normal.
<Shell.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.8*" />
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter TargetName="FlyoutItemIcon" Property="Image.Source" Value="icon_about.png"></Setter>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter TargetName="FlyoutItemIcon" Property="Image.Source" Value="cactus_24px.png"></Setter>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<Image x:Name="FlyoutItemIcon" Source="{Binding FlyoutIcon}"
Margin="5"
HeightRequest="45" >
</Image>
<Label Grid.Column="1"
Text="{Binding Title}"
FontAttributes="Italic"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
</Shell.ItemTemplate>
Update:
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
<ShellContent Title="About" Icon="icon_about.png" Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
</FlyoutItem>
I'm trying to stretch an image inside a Button which is inside a stackpanel and a grid but it doesn't works. On mobile size it works very well but when the app is for an Desktop it doesn't work anymore, we can see that the image overflows.
And what it looks like on desktop
My code:
<StackPanel x:Name="g5" Grid.Column="1" Grid.Row="1" Padding="20" Orientation="Vertical" >
<TextBlock Text="Site" FontSize="20"/>
<Button x:Name="websiteButton" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" Background="#fc0">
<Image x:Name="websiteImage" Source="Assets/website.png" NineGrid="0" Margin="20,20,20,20"/>
</Button>
</StackPanel>
Someone can tell me what is wrong and how i can stretch the image inside the button ? Btw it's a .png file.
Thanks everyone !!
Stack Panel with Vertical orientation does not impose any limits on the Children in terms of their height. It just ensures that they are stacked one on top of another. This means, that on Desktop the Button gets large width and therefore the image grows vertically to. One way to prevent this is to set MaxHeight of the Button or of the Image inside of it.
A better solution would be to use a Grid:
<Grid x:Name="g5" Height="200" HorizontalAlignment="Stretch" Padding="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Site" FontSize="20"/>
<Button Grid.Row="1" x:Name="websiteButton" HorizontalAlignment="Stretch" Margin="0" Background="#fc0">
<Image x:Name="websiteImage" Source="/Assets/Square150x150Logo.png" NineGrid="0" Margin="20,20,20,20"/>
</Button>
</Grid>
The second row of the Grid has "*" height, which means that it will grow to fill available space. This will limit the height of the button. The default Stretch value of the image is Uniform, which will ensure the image will look good inside the button.
#Romasz and #MZetko are right. But for layout targeting different device platform, my suggestion is that you can also use VisualStateManager to set the Width and Height properties for different app window's size for example like this:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
<!--for desktop-->
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="websiteButton.Width" Value="300" />
<Setter Target="websiteButton.Height" Value="300" />
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
<!--for mobile-->
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="websiteButton.Width" Value="150" />
<Setter Target="websiteButton.Height" Value="150" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
In my App, i am using a CommandBar with multiple AppBarButtons, on the top of the app. Now if i resize the window, i want that the AppBarButtons go to CommandBar.SecondaryButtons, if they does not fit anymor to the whole width of the window. As an example, in the default weather app, there is such an effect.
Second, i want to switch from the CommandBar on the Top, to a CommandBar on the bottom, like a CommandBar inside Page.BottomAppBar, on specific device families. I dont know, if i should set two CommandBars in my xaml and show the one, which meets the conditions, or if there is a better way. I like to do as much as possible with VisualStates, but i dont know how to achieve this.
I know these are two questions, but both points to the CommandBar, so i hope someone can help me?
Best regards
As an example, in the default weather app, there is such an effect.
You can use VisualStateManager to manages visual states and the logic for transitions between visual states for controls and use the Visibility property of the AppBarButton to show or hide it.
For example:
I add two AppBarButton in the CommandBar.PrimaryCommands and two AppBarButton in the CommandBar.SecondaryCommands. When the width of window less than 720, I set the Visibility property of the AppBarButton in CommandBar.PrimaryCommands to Collapsed. When the width of window large than 720 or equles to 720, I set the Visibility property of the AppBarButton in CommandBar.SecondaryCommands to Collapsed.
The XAML code:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PrimaryHome.Visibility" Value="Collapsed"/>
<Setter Target="PrimaryAdd.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SecondHome.Visibility" Value="Collapsed"/>
<Setter Target="SecondAdd.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
<Page.TopAppBar>
<CommandBar x:Name="TopCommands" >
<CommandBar.PrimaryCommands>
<AppBarButton Name="PrimaryHome" Icon="Home" Label="Home"/>
<AppBarButton Name="PrimaryAdd" Icon="Add" Label="Add" />
</CommandBar.PrimaryCommands>
<CommandBar.SecondaryCommands>
<AppBarButton Name="SecondHome" Icon="Home" Label="Home" />
<AppBarButton Name="SecondAdd" Icon="Add" Label="Add" />
</CommandBar.SecondaryCommands>
</CommandBar>
</Page.TopAppBar>
Second, i want to switch from the CommandBar on the Top, to a CommandBar on the bottom, like a CommandBar inside Page.BottomAppBar, on specific device families.
You can add the Page.TopAppBar and the Page.BottomAppBar in your XAML. And use VisualStateManager to manage which CommandBar should display on the
page.
For example:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="TopCommands.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="BottonCommands.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
<Page.TopAppBar>
<CommandBar x:Name="TopCommands" Visibility="Collapsed" >
<CommandBar.PrimaryCommands>
<AppBarButton Name="PrimaryHome" Icon="Home" Label="Home"/>
<AppBarButton Name="PrimaryAdd" Icon="Add" Label="Add" />
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.TopAppBar>
<Page.BottomAppBar>
<CommandBar x:Name="BottonCommands" Visibility="Collapsed">
<CommandBar.PrimaryCommands>
<AppBarButton Name="BottonPrimaryHome" Icon="Home" Label="Home"/>
<AppBarButton Name="BottonPrimaryAdd" Icon="Add" Label="Add" />
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.BottomAppBar>
For your first question: You can setup the buttons in Primary and Secondary sections of the CommandBar. Then use VisualStates to toggle the Visibility of them depend on app's width. OR you can do it in code entirely with SizeChanged event of the page.
Second question, lets create something like
<Page>
<Grid>
<!-- row definition here -->
<!-- Row 1 -->
<!-- Row 2 -->
<!-- Content -->
<Grid Grid.Row="0"/>
<!-- app bar -->
<CommandBar Grid.Row="1"/>
</Grid>
</Page>
Change the attached property Grid.Row to the desired number using VisualStates similar to question one.
In my Universal Windows 10 app, I have an animation that shrinks a custom control whose looks is applied via a template. It works as expected the first time it is run. The second time it is run, the start of the animation is rendered in a horrible resolution, apparently tainted by the previous run:
First time is on the left; second time on the right.
If, instead of using a custom control with a template, I hardcode everything in XAML, the problem doesn't occur.
If I grow rather than shrink the target, the problem doesn't occur.
Let me start with the non-templated version, which is shorter and easier to read than the templated version:
<Page
x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AnimationStates">
<VisualState x:Name="Show">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleX"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleY"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Hide" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
FontSize="122"
Text="Q">
<TextBlock.RenderTransform>
<ScaleTransform x:Name="transform" />
</TextBlock.RenderTransform>
</TextBlock>
<Button
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
Content="Animate!"
Click="OnAnimateClicked" />
</Grid>
</Page>
The code-behind is as follows:
public sealed partial class MainPage
{
public MainPage()
{
InitializeComponent();
}
private void OnAnimateClicked(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToState(this, "Hide", useTransitions: false);
VisualStateManager.GoToState(this, "Show", useTransitions: true);
}
}
This works fine every time. But. Instead of applying the ScaleTransform to the TextBlock's RenderTransform directly, I have a custom control with a template applied. For illustration purposes we can use a custom control that is little more than a placeholder:
public sealed class CustomControl : Control
{
}
Then change the XAML to replace the TextBlock with a CustomControl, applying a template to the CustomControl:
<Page
x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp">
<Grid>
<Grid.Resources>
<Style TargetType="local:CustomControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomControl">
<Grid>
<TextBlock Text="Q" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AnimationStates">
<VisualState x:Name="Show">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleX"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleY"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Hide" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<local:CustomControl
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
FontSize="122">
<local:CustomControl.RenderTransform>
<ScaleTransform x:Name="transform" />
</local:CustomControl.RenderTransform>
</local:CustomControl>
<Button
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
Content="Animate!"
Click="OnAnimateClicked"/>
</Grid>
</Page>
The first time I click the Animate button, this works exactly like the first version. The second and subsequent times, the initial animation rendering uses the really coarse resolution shown on the right:
The coarseness seems to be proportional to the shrinkage factor. Is this a bug of some sort (a failed optimization?), or is my understanding of templates flawed?
I am new to Windows Runtime programming and decided to get stuck in ahead of the release of Windows 10.
I am trying to design an adaptive page UI that looks something like as follows,
There is header "stuff" at the top and beneath it I want two columns, each with a textblock header and below it, a listview. The listview could be arbitraryheight and so the parent of the two blocks should, I think, be a scrollviewer.
On mobile however, this UI won't work as the screen is far to narrow, and so I would like to use a visualstate to rearrange the page so it looks as follows,
As you can see, the need for a scrollviewer is apparent to wrap this section. the "Other stuff" at the top should stay fixed however so it can be seen all the time.
I have tried a number of approaches to achieve this but haven't been able to manage it. What I currently have is this:
//.... Other Stuff ......
<ScrollViewer x:Name="SummaryScrollViewer" Grid.Row="2" HorizontalScrollBarVisibility="Disabled"
HorizontalScrollMode="Disabled" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" HorizontalContentAlignment="Center">
<RelativePanel x:Name="SummaryRelativePanel">
<Grid x:Name="lCol" Width="{Binding ActualWidth, ElementName=SummaryRelativePanel}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="lcolHead" Grid.Row="0" Text="TextBlock:"/>
<ListView x:Name="lcolList" Grid.Row="1">
</ListView>
</Grid>
<StackPanel x:Name="rCol" Orientation="Vertical" RelativePanel.RightOf="lCol">
<TextBlock x:Name="rcolHead" Text="TextBlock:"/>
<ListView x:Name="rcolList" Height="Auto">
</ListView>
</StackPanel>
</RelativePanel>
</ScrollViewer>
As you can see, I have tried to make the contents of each column both a stackpanel, and a grid, but I haven't been able to set the width of them to be, in "desktop view", half that of the containing relative panel, which should fill the full width of the screen, and in "mobile view" they should fill the full width of the parent.
I have found answers on how to bind the width to the ActualWidth property of the parent element as can be seen in the snippet, and this works, but I can't seem to make the two columns fill half of the parent each.
I wanted to use a RelativePanel so I can use the viewstate to change the properties of the right hand column to be either RightOf="LeftCol" or Below="LeftCol", and the widths should then be updated too to fill the width required.
Using a grid Should also be possible, define a 4x4 grid where in desktop the bottom two are collapse, or in mobile the right two are collapsed, but I was under the impression that this is the precise usecase the relativepanel was intended for.
In all examples of relativepanel they use relativepanel to move programmer defined with/height elements such as rectangles RelativePanel class.
It would also be possible to manually set ActualWidth of each column programatically from the code-behind but I don't know how to query which visual state the app/page is currently in to figure out how wide and where each column should be.
Any help and advice on what the "best" way to achieve such a thing would be would be greatly appreciated.
Here we go, let's begin that the bugs (or things I think are bugs)
1.- If I set a control with binding to the RelativePanel ActualWidth it just takes the first time, I mean, if I expand the window the control does not resize, so bug?
So let's do it with Grid:
<Grid x:Name="LayoutRoot" Background="Red" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowSizeStates" >
<VisualState x:Name="SmallScreen" >
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ContentLayoutRoot.Background" Value="Green"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[0].Height" Value="100"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[1].Height" Value="400"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[2].Height" Value="100"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[3].Height" Value="400"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[0].Width" Value="1*"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[1].Width" Value="0"/>
<Setter Target="SubHeaderOneLayout.(Grid.Row)" Value="0"/>
<Setter Target="ContentOneLayout.(Grid.Row)" Value="1"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Row)" Value="2"/>
<Setter Target="ContentTwoLayout.(Grid.Row)" Value="3"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Column)" Value="0"/>
<Setter Target="ContentTwoLayout.(Grid.Column)" Value="0"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="WideScreen">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1000" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ContentLayoutRoot.Background" Value="Purple"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[0].Height" Value="100"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[1].Height" Value="900"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[2].Height" Value="0"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[3].Height" Value="0"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[0].Width" Value="0.5*"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[1].Width" Value="0.5*"/>
<Setter Target="SubHeaderOneLayout.(Grid.Row)" Value="0"/>
<Setter Target="ContentOneLayout.(Grid.Row)" Value="1"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Row)" Value="0"/>
<Setter Target="ContentTwoLayout.(Grid.Row)" Value="1"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Column)" Value="1"/>
<Setter Target="ContentTwoLayout.(Grid.Column)" Value="1"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid x:Name="HeaderLayout" VerticalAlignment="Top" Height="32">
<TextBlock Text="Other Stuff" HorizontalAlignment="Center"/>
</Grid>
<ScrollViewer Grid.Row="1">
<Grid x:Name="ContentLayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="900"/>
<RowDefinition Height="0"/>
<RowDefinition Height="0"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="SubHeaderOneLayout" >
<TextBlock Text="Sub Header One" HorizontalAlignment="Center"/>
</Grid>
<Grid x:Name="SubHeaderTwoLayout" Grid.Column="1">
<TextBlock Text="Sub Header Two" HorizontalAlignment="Center"/>
</Grid>
<Grid x:Name="ContentOneLayout" Background="Orange" Grid.Row="1">
<TextBlock Text="ContentOne Layout" HorizontalAlignment="Center"/>
</Grid>
<Grid x:Name="ContentTwoLayout" Background="Orange" Grid.Row="1" Grid.Column="1">
<TextBlock Text="ContentOne Layout" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</ScrollViewer>
I could try to make it with Relative Panel but involves events, and more things, tell me if it is enough.
And, well the triggers I discovered by myself, you can get more info in my article in codeproject