This article is Day #4 in a series called 31 Days of Windows 8. Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.
Today we are going back to basics, and we’re going to look at some of the new layout controls that we have available in XAML applications. This article will specifically look at this list of controls:
- AppBar
- FlipView
- GridView
- ProgressRing
- ScrollViewer
- SemanticZoom
- WebView
If you want to see the entire list of controls available in XAML for Windows 8, you can head over to MSDN and read more here.
AppBar
When I first sat down to write this section, I remembered back to when I first started working with the ApplicationBar in Windows Phone development. It was pretty straightforward, but you had to create graphics for each icon, and then the Windows Phone OS added a circle for you.
When I dove into the AppBar for Windows 8, I was delighted to find that not only are graphics unnecessary for most of the icons you’ll use, but it’s also about as simple as it can be to implement. Here’s a look at the AppBar we are going to create:
As you can see in the image above (click to enlarge), we are going to be implementing both a top and bottom AppBar. While you can technically put anything you want in the AppBar, there are a couple of “rules” that should be noted:
1. The bottom AppBar is generally divided into two halves. The left is for context-specific commands, based on the content currently on the screen. The right is used for more universal commands that could be accessed from anywhere in your application.
2. The top AppBar is supposed to be used for navigation and other options needed in your app, similar to the ribbon you might find in one of the Office apps.
I mentioned earlier that you don’t need any artwork for the icons with the circles around them, and that’s absolutely true. In fact, you don’t need to do nearly anything other than create a button and apply one of the 202 default AppBar styles Microsoft has provided for you. They each use the “Segoe UI Icons” font for their iconography, and there’s a ton of them embedded in your StandardStyles.xaml file. Here’s a HUGE image that shows all of the icons available by default, in the order they are presented in the StandardStyles.xaml file:
Click the image to view it in its full-size glory. You’ll want to hold on to that one. (Also, a HUGE thanks to Mike Brown for creating an inverted version of this image for printing. It will definitely save you some ink.
OK, time to get to the implementation part of this section. In order to get the AppBar to respond to the user’s gestures, you simply need to create a new Page.TopAppBar or Page.BottomAppBar, like this:
<Page.BottomAppBar>
<AppBar>
<!-- Put any content here that you'd like. -->
</AppBar>
</Page.BottomAppBar>
You can honestly put anything want where the comments are in the code sample above, but if you’re looking to follow the rules, you’ll want to divide your AppBar into two sections. In that case, here’s a sample that incorporates a Grid to divine the AppBar in half, and uses two StackPanels to orient the icons appropriately. It’s the bottom bar from the screenshot I used above with the rainbow colored blocks at the top.
<Page.BottomAppBar>
<AppBar>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button x:Name="EditButton" Style="{StaticResource EditAppBarButtonStyle}" Tag="Edit" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Style="{StaticResource AddAppBarButtonStyle}" />
<Button Style="{StaticResource HelpAppBarButtonStyle}" />
<Button Style="{StaticResource DiscardAppBarButtonStyle}" />
<Button Style="{StaticResource DeleteAppBarButtonStyle}" />
</StackPanel>
</Grid>
</AppBar>
</Page.BottomAppBar>
You can see that for each icon on the bar, it simply consists of a Button control with a Style applied. As a reminder, all 202 of these styles can be found and edited in the StandardStyles.xaml file in your project. By default, all of these styles are commented out, so you can choose to uncomment all of them, or just uncomment the ones you’re actually using.
To demonstrate that we can put anything in an AppBar, however, let’s look at how I did the rainbow buttons at the top of the page.
<Page.TopAppBar>
<AppBar>
<StackPanel Orientation="Horizontal" Margin="10,10,10,10" Height="200">
<Rectangle Width="200" Height="200" Fill="Red" Margin="0,0,20,0" Tapped="Rectangle_Tapped" />
<Rectangle Width="200" Height="200" Fill="Orange" Margin="0,0,20,0" Tapped="Rectangle_Tapped" />
<Rectangle Width="200" Height="200" Fill="Yellow" Margin="0,0,20,0" Tapped="Rectangle_Tapped" />
<Rectangle Width="200" Height="200" Fill="Green" Margin="0,0,20,0" Tapped="Rectangle_Tapped" />
<Rectangle Width="200" Height="200" Fill="Blue" Margin="0,0,20,0" Tapped="Rectangle_Tapped" />
<Rectangle Width="200" Height="200" Fill="Purple" Margin="0,0,20,0" Tapped="Rectangle_Tapped" />
</StackPanel>
</AppBar>
</Page.TopAppBar>
I’ve added a bunch of Rectangle controls inside a StackPanel, and added a Tapped event to each of them. In my code-behind file, I determine the Fill color of the clicked rectangle, and set the background of the page to that color, using this method:
private void Rectangle_Tapped(object sender, TappedRoutedEventArgs e)
{
Rectangle rect = sender as Rectangle;
LayoutRoot.Background = rect.Fill;
}
Download the sample code at the bottom of this article to get a working version that will let you see this in action, as well as another page that contains all of the icon styles in code. When running the code, please note that the default Windows 8 gestures already work. Swiping in from the top or bottom of the screen will show the AppBar, as will right-clicking on the app itself. Give it a try!
FlipView
The FlipView control is one that I built from scratch several times for Windows Phone, because it didn’t exist. The basic purpose of a FlipView control is to allow to the user to “flip” through a specific group of content. In this example, we are going to have it flip through a set of images, but because the FlipView inherits from ItemsControl, we can bind any kind of data to it, including using DataTemplates for complex layouts. Here’s a quick look at our FlipView control in action (click to enlarge):
As you can see, we are provided with a set of forward and backward arrows that are content-aware of your position in the list of data, and will prevent moving past the beginning or end of the list. To implement this control couldn’t be simpler:
<FlipView x:Name="Flipper">
<Image Source="Assets/meme1.jpg" />
<Image Source="Assets/meme2.jpg" />
<Image Source="Assets/meme3.jpg" />
<Image Source="Assets/meme4.jpg" />
</FlipView>
All you need to do is add images to a FlipView, and you’ve got a simple image browser ready to go! For something more complex, you might want to add captions to your image browser. To do this, we can use FlipViewItems, with each Item holding its own unique values, like this:
<FlipView x:Name="Flipper">
<FlipViewItem>
<StackPanel>
<Image Source="Assets/meme1.jpg" Width="500" />
<TextBlock Text="Stupid Brain" TextAlignment="Center" FontSize="40" />
</StackPanel>
</FlipViewItem>
<FlipViewItem>
<StackPanel>
<Image Source="Assets/meme2.jpg" Width="500" />
<TextBlock Text="Drunk Baby" TextAlignment="Center" FontSize="40" />
</StackPanel>
</FlipViewItem>
<FlipViewItem>
<StackPanel>
<Image Source="Assets/meme3.jpg" Width="500" />
<TextBlock Text="Link Baby" TextAlignment="Center" FontSize="40" />
</StackPanel>
</FlipViewItem>
<FlipViewItem>
<StackPanel>
<Image Source="Assets/meme4.jpg" Width="500" />
<TextBlock Text="Keanu Mario" TextAlignment="Center" FontSize="40" />
</StackPanel>
</FlipViewItem>
</FlipView>
This results in each of our images having a small caption below it, like this (click it!):
There are many ways to extend this control, so I highly recommend checking out the FlipView control sample on MSDN as well. I specifically skipped over databinding in this example because we will cover it extensively in the next control on our list: the GridView.
GridView
The GridView is one of the signature controls that you will see in many Windows 8 applications. It shows up in nearly every demo/example you see, and is also the core of the Grid Application template in Visual Studio.
The GridView, like the FlipView and ListView, inherit from ItemsControl, which means they will take almost any type of XAML content. In this example, we are going to create the GridView in XAML, and populate it with a custom List of sample data. First, let’s define the sample data class, Player, which will be a simple list of players:
namespace Day4_NewControls
{
class Player
{
public string Name { get; set; }
public double Weight { get; set; }
public int Number { get; set; }
public double Height { get; set; }
public string TeamName { get; set; }
}
}
If you haven’t created a class in Visual Studio before, right click on your project name, and choose “Add > Class…” or press Shift + Alt + C. Name the class file Player.cs, and use the code above to define our simple object.
Next, we need to create our GridView control. Adding one to your page is simple, at first:
<GridView x:Name="mainGridView" Background="#33FFFFFF">
</GridView>
However, making it look and act the way you’d like takes a bit more work. If you’ve read previous articles I’ve written on databinding in XAML (check this one if you haven’t), you know that any control that inherits from ItemsControl can define an ItemTemplate which will specify how each object will be rendered on the screen. In this simple example, we are going to take each of our Player objects and render them as a rectangle in the GridView, with each of the data values displayed. Each box will look something like this:
So how do we do this? By defining a XAML layout that includes controls for each of the data values we want to display. Here’s the entire GridView again, with an ItemTemplate defined this time.
<GridView x:Name="mainGridView" Grid.Row="1" Background="#33FFFFFF" SelectionMode="Multiple">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Height="200" Width="200" Background="#33FFFFFF">
<TextBlock Text="{Binding Name}" FontSize="24" Foreground="White" Margin="5" />
<TextBlock Text="{Binding TeamName}" FontSize="16" Foreground="White" Margin="5"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Weight: " FontSize="16" Foreground="White" Margin="5"/>
<TextBlock Text="{Binding Weight}" FontSize="16" Foreground="White" Margin="5"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Height:" FontSize="16" Foreground="White" Margin="5" />
<TextBlock Text="{Binding Height}" FontSize="16" Foreground="White" Margin="5" />
</StackPanel>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
That gets us most of the way home. You can see that we have {Binding} statements for each property of our object, but we still haven’t actually created any objects to bind to this GridView control. We’re going to do that via code, so open up your Xaml.cs file.
In this example, I have created a new OnNavigatedTo event handler, and use this to populate my data. I am creating a new List<Player> collection, and then setting that collection as the ItemsSource of our “mainGridView” control.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
List<Player> players = new List<Player>();
players.Add(new Player { Name = "Frank Richard", TeamName = "Albany Old Schoolers", Height=74.2, Weight=245, Number=03});
players.Add(new Player { Name = "Buddy Hobbs", TeamName = "New York Elves", Height = 76.8, Weight = 227, Number = 04 });
players.Add(new Player { Name = "Ron Burgundy", TeamName = "San Diego Anchormen", Height = 77.1, Weight = 275, Number = 05 });
players.Add(new Player { Name = "Ricky Bobby", TeamName = "Talladega Racers", Height = 70.6, Weight = 198, Number = 06 });
players.Add(new Player { Name = "Chazz Reinhold", TeamName = "Washington Crashers", Height = 70.6, Weight = 198, Number = 06 });
mainGridView.ItemsSource = players;
}
If you’ve done it right, you should end up with an interface that looks like this:
While this is acceptable, when I started writing this example, I was expecting something more like the initial image I showed, which had 3 items in the first row, and 2 in the second. In order to define this type of layout, you can write tons more XAML, or you can take a look at the GridView.ItemsPanel.
Redefining the WrapGrid that is there by default will allow you to define the number of rows or columns that will be used. Inside your GridView control, add these few lines:
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Vertical" MaximumRowsOrColumns="2" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
Once you’ve done this, your GridView will look a little more familiar:
ProgressRing
While this is perhaps one of the simplest controls in this article, it’s no less important. The ProgressRing is designed to be that easy-to-use tool for distracting your user for a moment while you load or process something in the background. It’s a visual warning that you’re in the middle of something, and that you’d kindly appreciate the user’s patience for a moment. Here’s a look at one in action:
To get a ProgressRing on your page, you only need one line of XAML:
<ProgressRing x:Name="progressRing" IsActive="True" Visibility="Visible" Grid.Row="1"/>
In most practical applications, however, you’re going to need to control it via code as it is needed. This is as simple as modifying its Visibility property from Collapsed to Visible and back again.
One cool thing I discovered, however, is that it can also be scaled to many different sizes. For example, I’ve made the ProgressRing in the next screenshot 400 x 400. That’s the kind of message I want to send to my users. “Hold. Freaking. On.” 🙂
ScrollViewer
The ScrollViewer is another incredibly simple control that is practically invaluable. How many times have you had a large set of content that just wouldn’t fit on the screen, and you had to invent a scrolling or paging mechanism to make the rest of the data available to the user? The ScrollViewer makes it simple. Stuff your content inside a ScrollViewer, define which scrollbars you want to see, and you’re done. Here’s an example that has two StackPanels full of images, except that only the second one is inside a ScrollViewer.
<StackPanel Orientation="Horizontal">
<Image Source="Assets/meme1.jpg" Height="300" />
<Image Source="Assets/meme2.jpg" Height="300" />
<Image Source="Assets/meme3.jpg" Height="300" />
<Image Source="Assets/meme4.jpg" Height="300" />
<Image Source="Assets/meme1.jpg" Height="300" />
<Image Source="Assets/meme2.jpg" Height="300" />
<Image Source="Assets/meme3.jpg" Height="300" />
<Image Source="Assets/meme4.jpg" Height="300" />
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto">
<StackPanel Orientation="Horizontal">
<Image Source="Assets/meme1.jpg" Height="300" />
<Image Source="Assets/meme2.jpg" Height="300" />
<Image Source="Assets/meme3.jpg" Height="300" />
<Image Source="Assets/meme4.jpg" Height="300" />
<Image Source="Assets/meme1.jpg" Height="300" />
<Image Source="Assets/meme2.jpg" Height="300" />
<Image Source="Assets/meme3.jpg" Height="300" />
<Image Source="Assets/meme4.jpg" Height="300" />
</StackPanel>
</ScrollViewer>
</StackPanel>
SemanticZoom
When I first saw SemanticZoom in action, it was on the Windows 8 Start screen. Pinching to zoom allowed you to see a meta version of your apps and tiles. (If you don’t have a touch screen device, you can also use Ctrl + Scroll Wheel, or Since then, I’ve seen it in numerous great apps, including the Windows Store, News, and Netflix. Here’s a look at my Netflix app. No judging on the content, my entire family uses this account:
Zoomed In (default view):
Zoomed Out (meta view):
What’s nice about the SemanticZoom control is that we are given two states, ZoomedOutView and ZoomedInView, and we can generally put whatever we’d like in each view. (There’s actually very specific guidance about how and when to use SemanticZoom from Microsoft on MSDN.) In this example, we will have a group of elements from the Periodic Table, and we’ll show both the list of elements as well as a grouped view that shows them grouped into families, like Noble Gases or Alkali Metals, like the following screen shots:
So, to make this happen, we need to start with a SemanticZoom control. Add one to your page, like this:
<SemanticZoom>
<SemanticZoom.ZoomedInView>
<GridView>
</GridView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<GridView>
</GridView>
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
You’ll notice that there are several pieces that need to be added just to get started. First, there’s a node for ZoomedInView and ZoomedOutView. I like to put them in this order, because the ZoomedInView is the default view the user will see, and the ZoomedOutView is the “zoomed” view. It makes it easier to keep them straight in my mind.
Inside these containers, you need a control that implements the ISemanticZoomInformation interface, which is currently only the GridView and ListView controls. Since we’ve already used the GridView in this article, we’ll continue to use that one.
Before we do any of this, however, let’s talk data. This example is going to use elements from the periodic table, so we’ll need an Element class to get started.
namespace Day4_NewControls
{
class Element
{
public double AtomicWeight { get; set; }
public int AtomicNumber { get; set; }
public string Symbol { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public string State { get; set; }
}
}
In addition, we need to create and load some data into our page. Open up your Xaml.cs file and add a new OnNavigatedTo event handler method, like this one:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
List<Element> elements = new List<Element>();
elements.Add(new Element { AtomicNumber = 1, AtomicWeight = 1.01, Category = "Alkali Metals", Name = "Hydrogen", Symbol = "H", State = "Gas" });
elements.Add(new Element { AtomicNumber = 2, AtomicWeight = 4.003, Category = "Noble Gases", Name = "Helium", Symbol = "He", State = "Gas" });
elements.Add(new Element { AtomicNumber = 3, AtomicWeight = 6.94, Category = "Alkali Metals", Name = "Lithium", Symbol = "Li", State = "Solid" });
elements.Add(new Element { AtomicNumber = 4, AtomicWeight = 9.01, Category = "Alkaline Earth Metals", Name = "Beryllium", Symbol = "Be", State = "Solid" });
elements.Add(new Element { AtomicNumber = 5, AtomicWeight = 10.81, Category = "Non Metals", Name = "Boron", Symbol = "B", State = "Solid" });
elements.Add(new Element { AtomicNumber = 6, AtomicWeight = 12.01, Category = "Non Metals", Name = "Carbon", Symbol = "C", State = "Solid" });
elements.Add(new Element { AtomicNumber = 7, AtomicWeight = 14.01, Category = "Non Metals", Name = "Nitrogen", Symbol = "N", State = "Gas" });
elements.Add(new Element { AtomicNumber = 8, AtomicWeight = 15.999, Category = "Non Metals", Name = "Oxygen", Symbol = "O", State = "Gas" });
elements.Add(new Element { AtomicNumber = 9, AtomicWeight = 18.998, Category = "Non Metals", Name = "Fluorine", Symbol = "F", State = "Gas" });
elements.Add(new Element { AtomicNumber = 10, AtomicWeight = 20.18, Category = "Noble Gases", Name = "Neon", Symbol = "Ne", State = "Gas" });
elements.Add(new Element { AtomicNumber = 11, AtomicWeight = 22.99, Category = "Alkali Metals", Name = "Sodium", Symbol = "Na", State = "Solid" });
elements.Add(new Element { AtomicNumber = 12, AtomicWeight = 24.31, Category = "Alkaline Earth Metals", Name = "Magnesium", Symbol = "Mg", State = "Solid" });
elements.Add(new Element { AtomicNumber = 13, AtomicWeight = 26.98, Category = "Other Metals", Name = "Aluminum", Symbol = "Al", State = "Solid" });
elements.Add(new Element { AtomicNumber = 14, AtomicWeight = 28.09, Category = "Non Metals", Name = "Silicon", Symbol = "Si", State = "Solid" });
elements.Add(new Element { AtomicNumber = 15, AtomicWeight = 30.97, Category = "Non Metals", Name = "Phosphorus", Symbol = "P", State = "Solid" });
elements.Add(new Element { AtomicNumber = 16, AtomicWeight = 32.06, Category = "Non Metals", Name = "Sulfur", Symbol = "S", State = "Solid" });
elements.Add(new Element { AtomicNumber = 17, AtomicWeight = 35.45, Category = "Non Metals", Name = "Chlorine", Symbol = "Cl", State = "Gas" });
elements.Add(new Element { AtomicNumber = 18, AtomicWeight = 39.95, Category = "Noble Gases", Name = "Argon", Symbol = "Ar", State = "Gas" });
elements.Add(new Element { AtomicNumber = 19, AtomicWeight = 39.10, Category = "Alkali Metals", Name = "Potassium", Symbol = "K", State = "Solid" });
elements.Add(new Element { AtomicNumber = 20, AtomicWeight = 40.08, Category = "Alkaline Earth Metals", Name = "Calcium", Symbol = "Ca", State = "Solid" });
elements.Add(new Element { AtomicNumber = 21, AtomicWeight = 44.96, Category = "Transitional Metals", Name = "Scandium", Symbol = "Sc", State = "Solid" });
elements.Add(new Element { AtomicNumber = 22, AtomicWeight = 47.90, Category = "Transitional Metals", Name = "Titanium", Symbol = "Ti", State = "Solid" });
elements.Add(new Element { AtomicNumber = 23, AtomicWeight = 50.94, Category = "Transitional Metals", Name = "Vanadium", Symbol = "V", State = "Solid" });
elements.Add(new Element { AtomicNumber = 24, AtomicWeight = 51.996, Category = "Transitional Metals", Name = "Chromium", Symbol = "Cr", State = "Solid" });
elements.Add(new Element { AtomicNumber = 25, AtomicWeight = 54.94, Category = "Transitional Metals", Name = "Manganese", Symbol = "Mn", State = "Solid" });
elements.Add(new Element { AtomicNumber = 26, AtomicWeight = 55.85, Category = "Transitional Metals", Name = "Iron", Symbol = "Fe", State = "Solid" });
elements.Add(new Element { AtomicNumber = 27, AtomicWeight = 58.93, Category = "Transitional Metals", Name = "Cobalt", Symbol = "Co", State = "Solid" });
elements.Add(new Element { AtomicNumber = 28, AtomicWeight = 58.70, Category = "Transitional Metals", Name = "Nickel", Symbol = "Ni", State = "Solid" });
elements.Add(new Element { AtomicNumber = 29, AtomicWeight = 63.55, Category = "Transitional Metals", Name = "Copper", Symbol = "Cu", State = "Solid" });
elements.Add(new Element { AtomicNumber = 30, AtomicWeight = 65.37, Category = "Transitional Metals", Name = "Zinc", Symbol = "Zn", State = "Solid" });
elements.Add(new Element { AtomicNumber = 31, AtomicWeight = 69.72, Category = "Other Metals", Name = "Gallium", Symbol = "Ga", State = "Solid" });
elements.Add(new Element { AtomicNumber = 32, AtomicWeight = 72.59, Category = "Other Metals", Name = "Germanium", Symbol = "Ge", State = "Solid" });
elements.Add(new Element { AtomicNumber = 33, AtomicWeight = 74.92, Category = "Non Metals", Name = "Arsenic", Symbol = "As", State = "Solid" });
elements.Add(new Element { AtomicNumber = 34, AtomicWeight = 78.96, Category = "Non Metals", Name = "Selenium", Symbol = "Se", State = "Solid" });
elements.Add(new Element { AtomicNumber = 35, AtomicWeight = 79.90, Category = "Non Metals", Name = "Bromine", Symbol = "Br", State = "Liquid" });
elements.Add(new Element { AtomicNumber = 36, AtomicWeight = 83.80, Category = "Noble Gases", Name = "Krypton", Symbol = "Kr", State = "Gas" });
ElementData.Source = elements;
CategoryData.Source = from el in elements group el by el.Category into grp orderby grp.Key select grp;
}
For this example, I’ve included the first 36 elements in the periodic table, but you can expand this to more if you’ve got the time. Right now, you’re probably wondering about those last two lines referring to ElementData and CategoryData. These are CollectionViewSource elements that I’ve added to our XAML page’s Resources section. Here’s what my Page.Resources section looks like:
<Page.Resources>
<x:String x:Key="AppName">SemanticZoom Example</x:String>
<CollectionViewSource x:Name="ElementData" />
<CollectionViewSource x:Name="CategoryData" IsSourceGrouped="True"/>
</Page.Resources>
This is a simple way to define some collections of data in XAML, and populate them as we need from code. We’ll revisit these in a moment, but for now, they represent the two versions of our data, grouped and ungrouped.
Let’s focus on the ZoomedInView first, since it’s much more similar to our earlier example of a GridView. In the code sample below, I’ve included the entire ZoomedInView node, and you should notice that we’re declaring the ItemsSource in XAML rather than in code. We’re grabbing the CollectionViewSource for our raw data.
<SemanticZoom.ZoomedInView>
<GridView ItemsSource="{Binding Source={StaticResource ElementData}}" SelectionMode="None">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="150" Height="150" Background="#33FFFFFF">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="65" />
<ColumnDefinition Width="65" />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10" />
<RowDefinition Height="35" />
<RowDefinition Height="60" />
<RowDefinition Height="35" />
<RowDefinition Height="10" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding AtomicNumber}" Grid.Column="1" Grid.Row="1" FontWeight="Bold" />
<TextBlock Text="{Binding AtomicWeight}" Grid.Column="2" Grid.Row="1" TextAlignment="Right" FontWeight="Bold" />
<TextBlock Text="{Binding Symbol}" FontSize="50" Grid.Row="2" Grid.RowSpan="2" Grid.Column="1" Grid.ColumnSpan="2" TextAlignment="Center" Width="130" />
<TextBlock Text="{Binding Name}" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" TextAlignment="Center" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid MaximumRowsOrColumns="8" Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</SemanticZoom.ZoomedInView>
The rest of the markup is designed to a periodic table box. When rendered, it looks like this:
That’s about it for the ZoomedInView. On a side note, I chose Gallium for this screen shot because it’s awesome. It’s a metal that looks much like raw aluminum or tin, with a similar weight. What’s cool about it is that it has a melting point around 85F or 30C degrees. This means that when you grab a chunk of Gallium, it melts into a puddle in your hand, and looks much more like Mercury at that point. (Thanks to my friend Jim Tocco for introducing me to Gallium a few years ago.)
Now let’s move on to the ZoomedOutView. This is where things get a little more interesting. The following code sample should look nearly identical to the ZoomedInView, except the sizes are all smaller for our fonts and Grid, and that’s because it really is.
<SemanticZoom.ZoomedOutView>
<GridView x:Name="GridIn" ItemsSource="{Binding Source={StaticResource CategoryData}}" SelectionMode="None">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="75" Height="75" Background="#33FFFFFF">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5" />
<ColumnDefinition Width="33" />
<ColumnDefinition Width="32" />
<ColumnDefinition Width="5" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5" />
<RowDefinition Height="18" />
<RowDefinition Height="30" />
<RowDefinition Height="17" />
<RowDefinition Height="5" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding AtomicNumber}" Grid.Column="1" Grid.Row="1" FontSize="12" />
<TextBlock Text="{Binding AtomicWeight}" Grid.Column="2" Grid.Row="1" FontSize="12" TextAlignment="Right" />
<TextBlock Text="{Binding Symbol}" FontSize="25" Grid.Row="2" Grid.Column="1" Grid.RowSpan="2" Grid.ColumnSpan="2" TextAlignment="Center" Width="65" />
<TextBlock Text="{Binding Name}" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" FontSize="12" TextAlignment="Center" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</SemanticZoom.ZoomedOutView>
The way we are going to make our ZoomedOutView unique is by adding a GroupStyle to our GridView, which will add headers to each of our sections. The GroupStyle defines a HeaderTemplate for our section header layout, and binds to our Category name.
Here is what my GridView.GroupStyle markup looks like. You can insert this immediately after the GridView.ItemTemplate node from the previous example.
<GridView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Background="LightGray" Margin="0,0,20,0">
<TextBlock Text="{Binding Key}" Foreground="Black" Margin="30" FontSize="32" Width="350" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
The GroupStyle has its own HeaderTemplate, which defines what each section header looks like.
At this point, if you run your project (or download the sample at the bottom of this article), you will see that you can easily transition between the two SemanticZoom views, with just a little bit of XAML to make it happen.
I can’t recommend using SemanticZoom enough in your applications where it makes sense. Users will come to expect it, so don’t disappoint them. Give them the rich, immersive experience they deserve.
WebView
The WebView control is similiar to the WebBrowser from Windows Phone development. IN short, it is designed to allow you to show HTML content in your app from the web or from local files in your project. This becomes incredibly handy when many of the pages of your app would otherwise look identical to your website. You can crack open a WebView control and show the content without having to build any additional pages!
A WebView is also a great way to apply analytics and tracking codes to your apps as well. Make the WebView tiny, hide it in a corner of your application, and boom! You’ve got some easy in-app tracking.
Using the WebView control is simple. Define a source property, and off you go.
<WebView Source="http://31DaysOfWindows8.com" />
It’s another really simple control, but one you should always be aware of. You never know when you’ll need to embed some rich web content inside your application, and there isn’t an easier way.
Summary
This, long, exhaustive article covered off on seven of the new controls that are available to us in XAML development of Windows 8 applications. I hope you’ve picked up a trick or two on your way.
If you would like to download the entire solution and sample code for this article, click the button below:
Tomorrow, we’re going to get started on a series of articles related to contracts, and Day #5 will focus specifically on Settings within your app. See you then!
Leave a Reply