(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows 8 Metro Apps: The 8 Must-Know Tricks! Day 4

(2 votes)
Samidip Basu
>
Samidip Basu
Joined Aug 22, 2011
Articles:   16
Comments:   24
More Articles
0 comments   /   posted on Jul 30, 2012
Categories:   Windows 8 , Controls

This is Day # 4 in the Windows 8 development article series on common tips & tricks towards real-world Metro apps.  Now that our Metro app is well underway, time to make sure we are using the right tools for the job – the all-important controls for the best UX! And let’s not forget to inject our own brand in the app. Over the next several weeks, you’ll see 8 articles talk about some must-do things for Windows 8 Metro app developers. Simple & to the point, with some code examples on XAML/C# stack. Here’s the indexed list for the series:

Day 1: Know the ecosystem; Start
Day 2: Layout, Navigation & Visual States
Day 3: Semantic Zoom
Day 4: Controls & Styling
Day 5: Search, Share & Settings Contracts
Day 6: Data Persistence & Application Life-Cycle Management
Day 7: Use of OData or Web Services
Day 8: Live Services integration

Day 4: Controls & Styling

Content over chrome – one of the cornerstones of Metro design principles and very important to keep in mind as we design our Metro apps for Windows 8. Our UI should showcase content, minimize distractions & provide the user with the right hints to explore the app. One of the most important aspects of providing consistent & compelling UX are the controls that we put on our app canvas. It makes up for the very language that the end user uses to communicate with our app – pivotal, needless to say. So let’s explore our options on the XAML stack.

 

Container Controls:

Layout is the process of sizing & positioning objects in your UI and Container controls are your best friends. You have three main options for Metro apps:

Canvas – This container control is for absolute positioning child elements using explicit X & Y coordinates. The Canvas control uses Canvas.Left & Canvas.Top to position child elements as measured from the top left corner, with absolute drag & drop support in Visual Studio. While absolute positioning pinpoints the UI look & feel, it does not consider screen size/resolution; scaling could be an option to support variety of screen sizes.

Grid – This is the ubiquitous container control that supports dynamic layout, by placing child controls in a maze of rows & columns. Just like the HTML table, only less evil :). Child content is placed by defining RowDefinition & ColumnDefinition to fill up Grid.Rows & Grid.Columns. The flexible layout system is achieved by auto/*-sizing height/width of controls, so that content flows/wraps according to the space available to parent container.

StackPanel – The StackPanel is very similar to the Grid in supporting flexible layout, with the exception of it being 1-dimensional. Child elements are ‘stacked’ horizontally/vertically on top of each other based on the Orientation property of the parent StackPanel.

 

Collection Controls:

Collection of items – that happens to be the most common type of data that is presented in most applications, across platforms. To help keep your data fashionable, Metro apps give you several choices to present collection of items through specialized controls.

GridView – This is a control that present a collection of items in rows & columns that pan horizontally. This will possibly be the most recognizable Metro app control, presenting data in appropriately-sized rectangles with overlay description text. If bound to right datasets & done right, the GridView is sure to provide for an incredible inviting touch UX. Most importantly, the look & feel is completely customizable through ItemTemplates & DataTemplates. Sample control after next paragraph.

ListView – This control bind itself easily to a collection of items and is best suited for vertical scrolling.  Since it inherits from the same parent [ItemControls class] as the GridView, the display & touch interaction is completely customizable. Sample control below:

      

 

FlipView – This is a unique control that can be bound to a collection of items; but allows for flipping through the items one at a time sequentially, thus resulting in visually stunning touch interactions. Flip buttons appear on either edge that allows for forward & backward navigation; in addition, context indicator controls can be added to allow for jumping to a control. Samples below:

Image of a FlipView control

Image of a context indicator with a FlipView control

Semantic Zoom – The semantic zoom is the last of our collection controls and provides for wonderful touch interaction in providing a zoomed-in & zoomed-out view of grouped data. Want to know more about this control to provide for typical Windows 8 flavor?  – Try out our last full article on this topic HERE.

We can populate the above collection controls inline, or more practically, by data binding them to a collection of items. When data bound, the controls can be populated either by adding items to its Items collection, or by setting its ItemSource property, but we can't use both ways at the same time. To change how an item is displayed within each collection control, we can apply a style to the item container by setting the ItemContainerStyle property to a custom style, as we shall see in a bit.

Selection Controls:

Need the user to make a specific type of data selection? There are options galore to fit your needs; here are a few controls ..

Checkbox & RadioButton – As in any other XAML UI, these two allow for selection/de-selection of items. While both can allow multiple selections, the common use of RadioButton is to enforce mutual exclusivity in a group of items. Sample UIs below:

         

Toggle Button & Toggle Switch – As their name suggests, these controls allow switching between two states and allows for simple end user exercise of choice.  Sample UIs below:

       

ListBox & ComboBox – We should use either of these controls to let users select one or more values from a set of items that can be adequately represented using single lines of text. As a thumb rule, more than eight items call for ListBox or ComboBox; otherwise let’s revert to CheckBox or RadioButton. Sample controls below:

    

Slider – This control can be used to allow the user to select from a range of values by moving a finger along a track. Sample control below:

Some missing ones – Unfortunately, the HTML/CSS/JS world for Metro apps has a few controls that are yet to be available in the XAML stack of things. Notable among them are the Rating control & Date/Time Pickers. Patience, my friends :).

 

Filter/Navigation Controls:

Button – This is the generic XAML control used to navigate/select/filter/choose etc. This will be throughout the Windows 8 ecosystem, in various shapes & sizes. With the display being fully customizable, let us not forget to inject our Metro band for consistency throughout our application. Also, event handlers to respond to the button clicks can be wired up in the code-behind or through the use of Commands if using MVVM. Sample below:

App Bar – This control, like it’s Windows Phone counterpart, is wonderfully Metro and functions as a toolbar displaying context-specific commands/actions/filters. It can be tucked away at the bottom or the top, ready to aid the user on easy swipe. However, let us keep in mind that controls essential to the user’s workflow do belong on canvas, and not in the App Bar. Commands placed in the App Bar are best organized in category sets on either side of the screen horizontally stacked on each other. The reason – that is where our thumbs reach easily if holding a tablet in both hands! Other considerations for putting commands in the App Bar is to mind for dismissal modes and designing it to support Snapped/Portrait modes. Sample App Bar below:

 

Transient UI Controls:

Sometimes, we may need to present UI elements that are not constantly on the canvas, but show up on demand. Again the HTML world has a few more controls than the XAML ones for now; but UI elements like FlyOuts or Context Menu are easily re-creatable in XAML using hidden containers & entrance animations. Few example UI elements below:

MessageBox – Though not a XAML control by itself, the message dialog UI can be achieved using the PopupMenu XAML control. We need to be conservative in the usage of message dialogs, since it takes the user out of the immersive experience to a modal dialog; but urgent information, blocking questions & errors present some genuine needs of using a message dialog. Sample UI below:

Tooltip – This control displays a pop-up window with information about another UI element and helps users understand unfamiliar objects that aren't described directly in the UI. The Tooltip should only appear if the user does press & hold in case of touch or mouse hover over an UI element; it should never be deployed programmatically & dismissed easily. Since the user is not supposed to interact with the control, due diligence needs to put in to make sure it’s usage is appropriate. Sample UI below:

Progress Control – Our Metro apps might often be doing expensive operations; but the UI can never be locked up (achieved through the Async-Await magic which we will talk about later) and we need to show visual indication of progress made. XAML progress controls come in two flavors – the Progress Bar & the Progress Ring. They are both very Metro & have typical use cases. While the Progress Bar can be determinate/indeterminate, the Progress Ring is always indeterminate. Sample UI as below:

                  

While the list of controls above showed some of the Windows 8 Metro specific ones, there were plenty of controls we did not talk about. Bookmark THIS indexed list of controls & look it up as you need.

 

Custom Styling:

Now, in all the XAML controls above, what is common is complete customizability of the look & feel of the controls laid down in your canvas. Let us remember that Metro design language is a set of guiding principles; ultimately it is up to us to make it our own & make our brand. So, if you put a control on one of your pages and do not like the default behavior, simply change it; you will be pleasantly surprised how much can be configured.

Let me walk you through one common scenario. Say we added a GridView to our page; while everything works, the default styling does not sit well with the color palette in our application. For example, let’s take the SilverlightShow Articles demo app – when the article list is bound to the GridView, the default selected item indicator is on the left. What I really wanted was the one on the right!

 

DefaultSelection    

When it is comes to UI customization, guess who is your best friend? Yep – Expression Blend. Some of the XAML controls that we’ll put on our pages already have a fair amount of touch/mouse behavior built in. This is not shown on the XAML page, since it will be rather bulky if you were not looking to change a default behavior. So, some of the character of the controls is hidden, until you need to change it. In our case, we want to change the default ‘Selected’ item behavior of our GridView. Here are the steps, in words & then visually:

  • Open the XAML file in Expression Blend
  • Find the UI Control to style in the View Tree. In our case, it is the GridView inside Semantic Zoom control.
  • Edit the ItemContainerStyle template
  • Save the template style in the page or make it global in your app
  • Start recording & manipulate default behavior of chosen control sections on canvas
  • Save changes in Blend

OpenInBlend


EditItemContainerStyle

EditColorsInBlend

At the end of it all, we save the XAML page from Blend and close Blend. Visual Studio, if open, will throw a warning about files being changed outside the editor & ask you to reload. Voila – all your customization from Blend is now dropped in as XAML. This can be defined at the page level or in StandardStyles.xaml/App.xaml for global reusability. Here’s the sample code from our customized item template for the GridView:

   1: // On XAML Page.
   2: <GridView .... ItemContainerStyle="{StaticResource SLShowGridViewItemStyle}">
   3:  
   4: // Global Style.
   5: <Style x:Key="SLShowGridViewItemStyle" TargetType="GridViewItem">
   6:    <Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/>
   7:    <Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/>
   8:    <Setter Property="Background" Value="Transparent"/>
   9:    <Setter Property="TabNavigation" Value="Local"/>
  10:    <Setter Property="IsHoldingEnabled" Value="True"/>
  11:    <Setter Property="Margin" Value="0,0,2,2"/>
  12:    <Setter Property="Template">
  13:        <Setter.Value>
  14:            <ControlTemplate TargetType="GridViewItem">
  15:                <Border x:Name="OuterContainer">
  16:                    <VisualStateManager.VisualStateGroups>
  17:                        <VisualStateGroup x:Name="CommonStates">
  18:                            <VisualState x:Name="Normal"/>
  19:                            <VisualState x:Name="PointerOver">
  20:                                <Storyboard>
  21:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>
  22:                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectionBackground">
  23:                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
  24:                                    </ObjectAnimationUsingKeyFrames>
  25:                                </Storyboard>
  26:                            </VisualState>
  27:                            <VisualState x:Name="Pressed">
  28:                                <Storyboard>
  29:                                    <PointerDownThemeAnimation TargetName="ContentContainer"/>
  30:                                </Storyboard>
  31:                            </VisualState>
  32:                            <VisualState x:Name="PointerOverPressed">
  33:                                <Storyboard>
  34:                                    <PointerDownThemeAnimation TargetName="ContentContainer"/>
  35:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>
  36:                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectionBackground">
  37:                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
  38:                                    </ObjectAnimationUsingKeyFrames>
  39:                                </Storyboard>
  40:                            </VisualState>
  41:                            <VisualState x:Name="Disabled">
  42:                                <Storyboard>
  43:                                    <DoubleAnimation Duration="0" To="{StaticResource ListViewItemDisabledThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="contentPresenter"/>
  44:                                </Storyboard>
  45:                            </VisualState>
  46:                        </VisualStateGroup>
  47:                        <VisualStateGroup x:Name="FocusStates">
  48:                            <VisualState x:Name="Focused">
  49:                                <Storyboard>
  50:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisual"/>
  51:                                </Storyboard>
  52:                            </VisualState>
  53:                            <VisualState x:Name="Unfocused"/>
  54:                            <VisualState x:Name="PointerFocused"/>
  55:                        </VisualStateGroup>
  56:                        <VisualStateGroup x:Name="SelectionHintStates">
  57:                            <VisualStateGroup.Transitions>
  58:                                <VisualTransition GeneratedDuration="0:0:0.65" To="NoSelectionHint"/>
  59:                            </VisualStateGroup.Transitions>
  60:                            <VisualState x:Name="VerticalSelectionHint">
  61:                                <Storyboard>
  62:                                    <SwipeHintThemeAnimation ToHorizontalOffset="0" TargetName="SelectionBackground" ToVerticalOffset="15"/>
  63:                                    <SwipeHintThemeAnimation ToHorizontalOffset="0" TargetName="ContentBorder" ToVerticalOffset="15"/>
  64:                                    <SwipeHintThemeAnimation ToHorizontalOffset="0" TargetName="SelectedCheckMark" ToVerticalOffset="15"/>
  65:                                    <DoubleAnimationUsingKeyFrames Duration="0:0:0.500" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyph">
  66:                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.5"/>
  67:                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0.500" Value="0"/>
  68:                                    </DoubleAnimationUsingKeyFrames>
  69:                                </Storyboard>
  70:                            </VisualState>
  71:                            <VisualState x:Name="HorizontalSelectionHint">
  72:                                <Storyboard>
  73:                                    <SwipeHintThemeAnimation ToHorizontalOffset="-23" TargetName="SelectionBackground" ToVerticalOffset="0"/>
  74:                                    <SwipeHintThemeAnimation ToHorizontalOffset="-23" TargetName="ContentBorder" ToVerticalOffset="0"/>
  75:                                    <SwipeHintThemeAnimation ToHorizontalOffset="-23" TargetName="SelectedCheckMark" ToVerticalOffset="0"/>
  76:                                    <DoubleAnimationUsingKeyFrames Duration="0:0:0.500" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyph">
  77:                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.5"/>
  78:                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0.500" Value="0"/>
  79:                                    </DoubleAnimationUsingKeyFrames>
  80:                                </Storyboard>
  81:                            </VisualState>
  82:                            <VisualState x:Name="NoSelectionHint"/>
  83:                        </VisualStateGroup>
  84:                        <VisualStateGroup x:Name="SelectionStates">
  85:                            <VisualState x:Name="UnselectedSwiping">
  86:                                <Storyboard>
  87:                                    <DoubleAnimation Duration="0" To="0.5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectingGlyph"/>
  88:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
  89:                                </Storyboard>
  90:                            </VisualState>
  91:                            <VisualState x:Name="Selecting">
  92:                                <Storyboard>
  93:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
  94:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
  95:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectingGlyph"/>
  96:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
  97:                                </Storyboard>
  98:                            </VisualState>
  99:                            <VisualState x:Name="Selected">
 100:                                <Storyboard>
 101:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
 102:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
 103:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedCheckMark"/>
 104:                                </Storyboard>
 105:                            </VisualState>
 106:                            <VisualState x:Name="SelectedSwiping">
 107:                                <Storyboard>
 108:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
 109:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
 110:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedCheckMark"/>
 111:                                </Storyboard>
 112:                            </VisualState>
 113:                            <VisualState x:Name="Unselecting">
 114:                                <Storyboard>
 115:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
 116:                                </Storyboard>
 117:                            </VisualState>
 118:                            <VisualState x:Name="Unselected">
 119:                                <Storyboard>
 120:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
 121:                                </Storyboard>
 122:                            </VisualState>
 123:                            <VisualState x:Name="SelectedUnfocused">
 124:                                <Storyboard>
 125:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
 126:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
 127:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedCheckMark"/>
 128:                                </Storyboard>
 129:                            </VisualState>
 130:                        </VisualStateGroup>
 131:                        <VisualStateGroup x:Name="DragStates">
 132:                            <VisualStateGroup.Transitions>
 133:                                <VisualTransition GeneratedDuration="0:0:0.2" To="NotDragging"/>
 134:                            </VisualStateGroup.Transitions>
 135:                            <VisualState x:Name="NotDragging"/>
 136:                            <VisualState x:Name="Dragging">
 137:                                <Storyboard>
 138:                                    <DoubleAnimation Duration="0" To="{StaticResource ListViewItemDragThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="InnerDragContent"/>
 139:                                    <DragItemThemeAnimation TargetName="InnerDragContent"/>
 140:                                    <FadeOutThemeAnimation TargetName="SelectedCheckMarkOuter"/>
 141:                                    <FadeOutThemeAnimation TargetName="SelectedBorder"/>
 142:                                </Storyboard>
 143:                            </VisualState>
 144:                            <VisualState x:Name="DraggingTarget">
 145:                                <Storyboard>
 146:                                    <DropTargetItemThemeAnimation TargetName="OuterContainer"/>
 147:                                </Storyboard>
 148:                            </VisualState>
 149:                            <VisualState x:Name="MultipleDraggingPrimary">
 150:                                <Storyboard>
 151:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MultiArrangeOverlayBackground"/>
 152:                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MultiArrangeOverlayText"/>
 153:                                    <DoubleAnimation Duration="0" To="{StaticResource ListViewItemDragThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentBorder"/>
 154:                                    <FadeInThemeAnimation TargetName="MultiArrangeOverlayBackground"/>
 155:                                    <FadeInThemeAnimation TargetName="MultiArrangeOverlayText"/>
 156:                                    <DragItemThemeAnimation TargetName="ContentBorder"/>
 157:                                    <FadeOutThemeAnimation TargetName="SelectionBackground"/>
 158:                                    <FadeOutThemeAnimation TargetName="SelectedCheckMarkOuter"/>
 159:                                    <FadeOutThemeAnimation TargetName="SelectedBorder"/>
 160:                                    <FadeOutThemeAnimation TargetName="PointerOverBorder"/>
 161:                                </Storyboard>
 162:                            </VisualState>
 163:                            <VisualState x:Name="MultipleDraggingSecondary">
 164:                                <Storyboard>
 165:                                    <FadeOutThemeAnimation TargetName="ContentContainer"/>
 166:                                </Storyboard>
 167:                            </VisualState>
 168:                        </VisualStateGroup>
 169:                        <VisualStateGroup x:Name="ReorderHintStates">
 170:                            <VisualStateGroup.Transitions>
 171:                                <VisualTransition GeneratedDuration="0:0:0.2" To="NoReorderHint"/>
 172:                            </VisualStateGroup.Transitions>
 173:                            <VisualState x:Name="NoReorderHint"/>
 174:                            <VisualState x:Name="BottomReorderHint">
 175:                                <Storyboard>
 176:                                    <DragOverThemeAnimation Direction="Bottom" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
 177:                                </Storyboard>
 178:                            </VisualState>
 179:                            <VisualState x:Name="TopReorderHint">
 180:                                <Storyboard>
 181:                                    <DragOverThemeAnimation Direction="Top" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
 182:                                </Storyboard>
 183:                            </VisualState>
 184:                            <VisualState x:Name="RightReorderHint">
 185:                                <Storyboard>
 186:                                    <DragOverThemeAnimation Direction="Right" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
 187:                                </Storyboard>
 188:                            </VisualState>
 189:                            <VisualState x:Name="LeftReorderHint">
 190:                                <Storyboard>
 191:                                    <DragOverThemeAnimation Direction="Left" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
 192:                                </Storyboard>
 193:                            </VisualState>
 194:                        </VisualStateGroup>
 195:                        <VisualStateGroup x:Name="DataVirtualizationStates">
 196:                            <VisualState x:Name="DataAvailable"/>
 197:                            <VisualState x:Name="DataPlaceholder">
 198:                                <Storyboard>
 199:                                    <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PlaceholderTextBlock">
 200:                                        <DiscreteObjectKeyFrame KeyTime="0">
 201:                                            <DiscreteObjectKeyFrame.Value>
 202:                                                <Visibility>Visible</Visibility>
 203:                                            </DiscreteObjectKeyFrame.Value>
 204:                                        </DiscreteObjectKeyFrame>
 205:                                    </ObjectAnimationUsingKeyFrames>
 206:                                    <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PlaceholderRect">
 207:                                        <DiscreteObjectKeyFrame KeyTime="0">
 208:                                            <DiscreteObjectKeyFrame.Value>
 209:                                                <Visibility>Visible</Visibility>
 210:                                            </DiscreteObjectKeyFrame.Value>
 211:                                        </DiscreteObjectKeyFrame>
 212:                                    </ObjectAnimationUsingKeyFrames>
 213:                                </Storyboard>
 214:                            </VisualState>
 215:                        </VisualStateGroup>
 216:                    </VisualStateManager.VisualStateGroups>
 217:                    <Grid x:Name="ReorderHintContent" Background="Transparent">
 218:                        <Path x:Name="SelectingGlyph" Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{StaticResource ListViewItemCheckSelectingThemeBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Right" Height="13" Margin="0,9.5,9.5,0" Opacity="0" Stretch="Fill" VerticalAlignment="Top" Width="15"/>
 219:                        <Border x:Name="ContentContainer">
 220:                            <Grid x:Name="InnerDragContent">
 221:                                <Border x:Name="HintGlyphBorder" HorizontalAlignment="Right" Height="40" Margin="4" Opacity="0" VerticalAlignment="Top" Width="40">
 222:                                    <Path x:Name="HintGlyph" Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{StaticResource ListViewItemCheckHintThemeBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Right" Height="13" Margin="0,5.5,5.5,0" Opacity="0" Stretch="Fill" VerticalAlignment="Top" Width="15"/>
 223:                                </Border>
 224:                                <Rectangle x:Name="PointerOverBorder" Fill="{StaticResource ListViewItemPointerOverBackgroundThemeBrush}" IsHitTestVisible="False" Margin="1" Opacity="0"/>
 225:                                <Rectangle x:Name="FocusVisual" IsHitTestVisible="False" Opacity="0" Stroke="{StaticResource ListViewItemFocusBorderThemeBrush}" StrokeThickness="2"/>
 226:                                <Rectangle x:Name="SelectionBackground" Fill="{StaticResource ListViewItemSelectedBackgroundThemeBrush}" Margin="4" Opacity="0"/>
 227:                                <Border x:Name="ContentBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="4">
 228:                                    <Grid>
 229:                                        <ContentPresenter x:Name="contentPresenter" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
 230:                                        <TextBlock x:Name="PlaceholderTextBlock" Foreground="{x:Null}" IsHitTestVisible="False" Margin="{TemplateBinding Padding}" Text="Xg" Visibility="Collapsed"/>
 231:                                        <Rectangle x:Name="PlaceholderRect" Fill="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" IsHitTestVisible="False" Visibility="Collapsed"/>
 232:                                        <Rectangle x:Name="SelectedBorder" IsHitTestVisible="False" Opacity="0" Stroke="#FFFF8000" StrokeThickness="{StaticResource GridViewItemSelectedBorderThemeThickness}"/>
 233:                                        <Rectangle x:Name="MultiArrangeOverlayBackground" Fill="{StaticResource ListViewItemDragBackgroundThemeBrush}" IsHitTestVisible="False" Opacity="0"/>
 234:                                    </Grid>
 235:                                </Border>
 236:                                <Border x:Name="SelectedCheckMarkOuter" HorizontalAlignment="Right" IsHitTestVisible="False" Margin="4" Padding="{TemplateBinding BorderThickness}" VerticalAlignment="Top">
 237:                                    <Grid x:Name="SelectedCheckMark" Height="40" Opacity="0" Width="40">
 238:                                        <Path x:Name="SelectedEarmark" Data="M0,0 L40,0 L40,40 z" Fill="#FFFF8000" Stretch="Fill"/>
 239:                                        <Path Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{StaticResource ListViewItemCheckThemeBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Right" Height="13" Margin="0,5.5,5.5,0" Stretch="Fill" VerticalAlignment="Top" Width="15"/>
 240:                                    </Grid>
 241:                                </Border>
 242:                                <TextBlock x:Name="MultiArrangeOverlayText" Foreground="{StaticResource ListViewItemDragForegroundThemeBrush}" FontSize="26.667" FontFamily="{StaticResource ContentControlThemeFontFamily}" IsHitTestVisible="False" Margin="18,9,0,0" Opacity="0" TextWrapping="Wrap" Text="{Binding TemplateSettings.DragItemsCount, RelativeSource={RelativeSource Mode=TemplatedParent}}" TextTrimming="WordEllipsis"/>
 243:                            </Grid>
 244:                        </Border>
 245:                    </Grid>
 246:                </Border>
 247:            </ControlTemplate>
 248:        </Setter.Value>
 249:    </Setter>
 250: /Style>

 

As you can see, it is substantial and difficult to hand-code. But do it once in Blend UI, save as global style & you can reuse anywhere in your application. This approach also has the benefit of the flexibility of handing your XAML file to the designer (if you have one) and allow for customization as you work on your code; when done, simply load up the changed XAML. Same technique can be applied to most other UI controls discussed above. So, go ahead – use the right controls & make your app truly yours!

PS: Control gallery image courtesy from MSDN.

 

Conclusion

That’s it for today. The crux of this article was to talk about the various UI controls available in the XAML stack and how to customize their styles to inject your own brand for a delightful UX.
 
See you next time as we dive into some OS Contracts for Windows 8 Metro apps. Thanks for reading!

 

About Author

ActualPic

Samidip Basu (@samidip) is a technologist, gadget-lover and MSFT Mobility Solutions Lead for Sogeti USA working out of Columbus OH. With a strong developer background in Microsoft technology stack, he now spends much of his time in spreading the word to discover the full potential of Windows Phone/Windows 8 platforms & cloud-supported mobile solutions in general. He passionately helps run the Metro Developer User Group (http://themetrodeveloperusergroup.com/), labors in M3 Conf (http://m3conf.com/) organization and can be found with at-least a couple of hobbyist projects at any time. His spare times call for travel and culinary adventures with the wife. Find out more at http://samidipbasu.com.


Subscribe

Comments

No comments

Add Comment

Login to comment:
  *      *       

From this series