I have many app is the Windows 8 store now. My Sudoku Free app is the most popular one. It has almost 500.000 downloads and it is played around 13.000 a day. Until recently I received many mails on how to use the app. My support email address is in the Settings panel. Most of these mails where request to add features to the game like 'can I validate a puzzle?', 'can I solve a puzzle?', 'can I get statistics?' or 'can I get a hint?'. Those features are all available in the AppBar of the game. My conclusion is that the average user is still not aware that the AppBar can exist.
To make my users aware of the AppBar I added a peek behavior to it. When you start a sudoku puzzle the AppBar peeks out for just a second, see video. After the implementation I got almost no more of those emails any more.
Solution
The implementation of a peeking AppBar is very easy. For my demo I used Blend for Visual Studio to generate a new project using the 'Grid App (XAML)' template. Next I add an AppBar to the ItemDetailPage page.
I named the AppBar 'MyBottomAppBar' and set the Background color to Green. I also added a Button to the first StackPanel of the AppBar. I have reset the Content property of the Button and selected the 'AddAppBarButtonStyle' Style. Before I could do that I had to uncomment this Style from the 'Common\StandardStyles.xaml' resource dictionary.
<common:LayoutAwarePage x:Name="pageRoot" x:Class="PeekingAppBar.ItemDetailPage" DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:PeekingAppBar" xmlns:data="using:PeekingAppBar.Data" xmlns:common="using:PeekingAppBar.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <!-- Collection of items displayed by this page --> <CollectionViewSource x:Name="itemsViewSource" Source="{Binding Items}" d:Source="{Binding AllGroups[0].Items, Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}" /> </Page.Resources> <common:LayoutAwarePage.BottomAppBar> <AppBar x:Name="MyBottomAppBar" Background="#FF00CD00"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <StackPanel Orientation="Horizontal"> <Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Style="{StaticResource AddAppBarButtonStyle}" /> </StackPanel> <StackPanel Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal" /> </Grid> </AppBar> </common:LayoutAwarePage.BottomAppBar> <!-- This grid acts as a root panel for the page that defines two rows: * Row 0 contains the back button and page title * Row 1 contains the rest of the page layout --> <Grid Style="{StaticResource LayoutRootStyle}" DataContext="{Binding Group}" d:DataContext="{Binding AllGroups[0], Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}"> <Grid.RowDefinitions> <RowDefinition Height="140" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <!-- The remainder of the page is one large FlipView that displays details for one item at a time, allowing the user to flip through all items in the chosen group --> <FlipView x:Name="flipView" AutomationProperties.AutomationId="ItemsFlipView" AutomationProperties.Name="Item Details" TabIndex="1" Grid.RowSpan="2" ItemsSource="{Binding Source={StaticResource itemsViewSource}}">
To implement the peeking behavior I wrote just a few lines of C# code in the Code Behind of the page. I added a subscription to the Loaded event of the page in the constructor. In the ItemDetailPage_Loaded method I used the Task.Delay() method to pause for a half second. Then I opened the AppBar, paused again but now for 1 second and then closed it again. The ItemDetailPage_Loaded was marked as async to allow the 'await' on the Task.Delay() call. This async keyword is not allowed in a constructor. This is the reason why I wrote my code in the Loaded eventhandler and not in the constructor of the page.
public sealed partial class ItemDetailPage : PeekingAppBar.Common.LayoutAwarePage { public ItemDetailPage() { this.InitializeComponent(); this.Loaded += ItemDetailPage_Loaded; } private async void ItemDetailPage_Loaded(object sender, RoutedEventArgs e) { await Task.Delay(500); MyBottomAppBar.IsOpen = true; await Task.Delay(1000); MyBottomAppBar.IsOpen = false; }
Closure and download
I hope you like my solution. Maybe you can use it in your apps too. You can download my code below.
Cheers,
Fons
DownloadAll postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.
Blog comments
Mark Monster
22-May-2013 11:50