Panorama-like XAML layout with state and transitions - xaml

In my app I'd like to have a page layout as shown on this picture:
It has two content blocks (depicted as plain and shaded rectangles) and two states. In normal (1st) state plain block takes all the screen and is fully visible while shaded is hidden behind screen. In 2nd state shaded block is fully visible and also a small part of plain block is on screen, the rest of it is hidden.
I'd also like to have a nice transition from one state to another. I understand I'd probably need to use ViewStates for this. What I don't understand it what XAML control should I use to represent content blocks. So this is the question: what XAML controls would allow me to express this layout as elegantly and concisely as possible?

How about a grid with 2 rows. A pivot control with your 2 states in each pivot item in first row and your fixed content in second row.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" Background="Red">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<phone:Pivot Margin="0,-24,0,0">
<phone:PivotItem Background="Blue">
<StackPanel>
<TextBlock Text="Transition content 1" />
</StackPanel>
</phone:PivotItem>
<phone:PivotItem Background="Brown">
<StackPanel>
<TextBlock Text="Transition content 2" />
</StackPanel>
</phone:PivotItem>
</phone:Pivot>
<StackPanel Grid.Row="1" Margin="12,0,12,0">
<TextBlock Text="Fixed content" />
</StackPanel>
</Grid>
Swiping on the top box will animate as the standard pivot animation.
If you don't want the user to be able to flick and rather control the two states programmatically then you can simply add IsHitTestVisible="False" on the root pivot control then set the SelectedIndex on the pivot to switch between states.

Related

Transparent Grid in Windows Phone?

I'm trying to write a page for WP8 which plays video, using the MediaElement API.
I am having difficulties in placing the play/pause controls over the video.
I am currently using a grid to house the controls over the video. The problem is that I cannot make the grid transparent. This is the XAML -
<StackPanel Background="Transparent">
<MediaElement Name="media" Source="http://video-js.zencoder.com/oceans-clip.mp4" AutoPlay="True"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<!-- Play button. -->
<!-- Pause button. -->
<Grid Background="Transparent" VerticalAlignment="Bottom" Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*"/>
<ColumnDefinition Width=".5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="85" />
</Grid.RowDefinitions>
<Image Grid.Column="0" Source="Assets\transport.pause.png" Height="79" Width="79"/>
<Image Grid.Column="1" Source="Assets\transport.play.png" Height="79" Width="79"/>
</Grid>
</StackPanel>
I can still see a black portion where the Grid is.
Is there a better way to accomplish this?
You've put the controls in a StackPanel. That means that you'll end up with:
StackPanel
MediaElement
Grid
Button/Image
Button/Image
A StackPanel is designed to stack controls either horizontally or vertically. It is not for overlaying controls. So, the black background you're seeing is the background beneath the Grid, which is likely the default background brush/color of the application (black).
If you instead were to use a Grid to host the controls, you can use an overlay as you need to:
<Grid x:Name="ContentPanel" >
<Grid>
<MediaElement Name="media" Source="Assets/sample_mpeg4.mp4"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Grid Background="#80000000" VerticalAlignment="Center" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" >Pause</Button>
<Button Grid.Column="1" Click="Button_Click_1" >Play</Button>
</Grid>
</Grid>
</Grid>
It's now:
Grid
MediaElement
Grid
Button
Button
It would look something like this:
Using the Grid, I've put both the MediaElement and the inner Grid in the same cell (by using the default attached property values for Row and Column which are `0').
In the above code, I've used a Grid to layout the MediaElement and another Grid which will layout the two Buttons I've used. In this case, I've centered the Grid with the Buttons so that the buttons appear in the center of the MediaElement.
I've also used a somewhat transparent Background for the Grid which contains the buttons.
I've dealt with this issue before but can't remember exactly how I solved it. I remember researching this, which is using visual media as a Brush to then paint the background of the Grid that houses the buttons. IIRC, the issue is not necessarily with the Grid, it's with anything overlaying the MediaElement. Because of some special drawing procedure involved with the MediaElement it doesn't handle overlays and transparencies well. There is a solution, but like I said I can't completely remember. But try out using the video as a Brush for the background of the Grid.

Windows phone 8 - Pivot Active, Inactive Header template

I'd like to use different templates for the header of my pivot, if it's selected/active id like to use template A, if it's inactive/not selected, I'd like to use template B.
What I would like to do is pretty much the same as the facebook app for windows phone, where a small triangle/arrow is displayed on the active pivot. I'm not 100% sure how this is designed, if the icon and arrow is the header template, or if it's just the arrow, or if it's pivot at all...
I would appreciate if someone would shed some light on how this kind of UI can be achieved.
Ended up with a work-around for this
I removed the pivot header entirely and created a stand alone control to navigate the pivot
The nav-viewmodel, shared between the pivot and the Nav control, have a SelectedPage property, which changes when you navigate in the Nav control:
<AppControls:Nav Grid.Row="0"/>
That gives me full control of the layout of the selected menu item.
The SelectedPage property is bound to the pivots selectedindex:
full markup:
<Grid x:Name="LayoutRoot" DataContext="{Binding Nav, Source={StaticResource Locator}}" Background="#E8E8E8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--ContentPanel - place additional content here-->
<AppControls:Nav Grid.Row="0"/>
<phone:Pivot SelectedIndex="{Binding SelectedPage, Mode=TwoWay}" Grid.Row="1" x:Name="MainGui">
<phone:PivotItem x:Name="FrontPage">
<AppControls:Topnav Grid.Row="1" />
</phone:PivotItem>
<phone:PivotItem x:Name="PlacesPage">
<AppControls:PlacesControl Grid.Row="1"/>
</phone:PivotItem>
<phone:PivotItem x:Name="MapPage">
<AppControls:MapControl Grid.Row="1"/>
</phone:PivotItem>
<phone:PivotItem x:Name="SettingsPage">
<AppControls:Settings Grid.Row="1" />
</phone:PivotItem>
</phone:Pivot>
</Grid>

Repeat EntranceThemeTransition

I have a simple TabControl done using templated RadioButtons and Grids which change visibility when IsChecked on a RadioButton changes, something like this:
<Grid Name="TabGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<RadioButton x:Name="RadioButton1" Content="Latest" Style="{StaticResource TabRadioButtonStyle}" IsChecked="True" GroupName="G1"/>
<RadioButton x:Name="RadioButton2" Content="Popular" Style="{StaticResource TabRadioButtonStyle}" IsChecked="False" GroupName="G1" Margin="30,0,0,0" />
</StackPanel>
Now, every grid inside has EntranceThemeTransition defined, something like this:
<GridGrid.Row="1" Visibility="{Binding ElementName=RadioButton1, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</Grid.ChildrenTransitions>
As I understand, the EntranceThemeTransition displays only when the items are first shown. Is there a way to force EntranceThemeTransition to repeat every time the visibility of the Grid changes?
This doesn't exactly answer your questions but I think will help many people landing on here:
If you want to repeat the entrance animations for items in a databound listbox, I have found only one way of doing this:
Set the DataContext of the listbox to null (this removes the items).
Set the DataContext of the listbox back to your list/observable collection (this recreates the items and adds them to the listbox with an animation).
By reseting the DataContext you are creating new listbox items and they aren't marked as having entered the view yet.
In regards to your question; I think you'll need to create a new version of the grid to play the entrance animation again.

ItemsControl contents overflow the grid row before getting clipped

I have a page with a two row grid. In the first row I have a databound ItemsControl and in the second row a simple textbox.
The problem is that while the page is loading (i.e. it is animated into the view), the ItemScontrol's content overflows over the entire grid. Only after the page is fully shown after a short while (it seems exactly 1 second, although I haven't measured it), the contents get properly clipped to the Grid row.
Here's what happens while loading the page (not that there are some transitions on this screenshot however they do not have an effect on this behavior):
After the page is fully loaded, contents get clipped properly:
Here's the pseudo-XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<ItemsControl ItemsSource="{Binding}">
<!-- grid for each row -->
</ItemsControl>
</StackPanel>
<StackPanel Grid.Row="1">
<TextBox />
</StackPanel>
</Grid>
I figured out that clipping works properly if I set the ItemsControl's (but not the StackPanel's!) height to a fixed value, however of course I don't want the height to be fixed.
Any ideas?

How to set a RichTextBox in Silverlight 4 to fit it's parent height and maintain it on resize?

I am having hard times figuring this out. Here is what I need:
<StackPanel x:Name="container" VerticalAlignment="Stretch">
<RichTextBox Height="???" />
</StackPanel>
Basically what I know I can do is to bind RichTextBox Height to it's parent's height ( Height="{Binding ElementName=container, Path=ActualHeight}". Unfortunately this only works on load, because as it seems ActualHeight and ActualWidth don't notify for changes.
So what is the best way in Silverlight 4 to tell RichTextBox or TextBlock, it doesn't matter, to fill it's parent height, and maintain scrollbar if it's content height is bigger. Is the only way to bind some Resize events and maintain the height explicitly? That seems really ugly to me? Have anybody had this problem as well?
Any resources or information is highly appreciated! Thanks.
Ivan,
The best way to solve this is to use a Grid as the parent for the RickTextBox, instead of a StackPanel. By default, a Grid will "Strectch" its content to take up all of the available space. A StackPanel will only Stretch its content in one diminsion.
As an example, paste the following XAML into my XamlViewer to see the difference:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<RichTextBox
Foreground="Blue" FontSize="24" Background="Yellow">
<Paragraph>RichTextBox inside a StackPanel</Paragraph>
</RichTextBox>
</StackPanel>
<Grid Grid.Row="1">
<RichTextBox
Foreground="Blue" FontSize="24" Background="Tan">
<Paragraph>RichTextBox inside a Grid</Paragraph>
</RichTextBox>
</Grid>
</Grid>
</UserControl>
Good luck,
Jim McCurdy, Face to Face Software and YinYangMoney