tips for building a windows store app using xaml and c
TRANSCRIPT
patterns & practices Symposium 2013
Tips for building a Windows Store app using XAML and C#: The Kona project
Francis [email protected]
Kona C# Background Tips and Lessons
Learned for building C# Windows Store apps
Agenda
• Modularity• UI Composition• Region
Navigation• Decoupled
Communication• Commands• MVVM Support
Prism for WPF, Silverlight and Windows Phone
End-to-end shopping app sample that provides guidance to C# developers on how to use modern C#, asynchronous programming, XAML, and the .NET for Windows Store apps to build a world-ready app for the global market. Projected to ship March 2013
The Kona Project
Rethink Prism Scenarios for Windows Store • Modularity
• UI Composition• Region Navigation• Decoupled
Communication• Commands• MVVM Support
??
Walkthrough
Demo AdventureWorks Shopper
Tips and Lessons Learned
1. Leverage background in Windows Phone developmentWindows Phone apps Windows Store apps
Deactivate/Tombstoned/Reactivate Suspend/Terminate/Resume
Microsoft Push Notification Service (MPN)
Windows Push Notification Service (WNS)
Windows Phone Marketplace certification
Windows Store app certification & Application Excellence Review (AER)
App manifest declares capabilities App manifest declares capabilities
2. Focus on AttachedBehaviors• No Blend
Behavior<T>• No
BindingExpressions• Break out your
AttachedBehavior experience and ROCK ON!
3. Push Notification requires Windows Store registration
• Make sure to register your app with the Windows Store to get proper credentials (SID & secret key)
• Purely sideloaded apps won’t be able to receive notifications from Windows Notification Service (WNS)
1: async Task<int> AccessTheWebAsync()
2: {
3: HttpClient client = new HttpClient();
4: Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
5: DoIndependentWork();
6:
7: string urlContents = await getStringTask;
8: return urlContents.Length;
9: }
4. async & await are your friends
Pages and Navigation
Navigation supportprotected virtual void GoHome(object sender, RoutedEventArgs e)protected virtual void GoBack(object sender, RoutedEventArgs e)protected virtual void GoForward(object sender, RoutedEventArgs e)
Visual state switchingpublic void StartLayoutUpdates(object sender, RoutedEventArgs e)public void StopLayoutUpdates(object sender, RoutedEventArgs e)
Process lifetime managementprotected override void OnNavigatedTo(NavigationEventArgs e)protected override void OnNavigatedFrom(NavigationEventArgs e)protected virtual void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)protected virtual void SaveState(Dictionary<String, Object> pageState)
5. Use the LayoutAwarePage class to provide navigation, state management, and visual state management
XAML:
<Button Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
<UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
Navigation & Visual State Support
protected override void SaveState(System.Collections.Generic.Dictionary<string, object> pageState){ var virtualizingStackPanel =
VisualTreeUtilities.GetVisualChild<VirtualizingStackPanel>(itemGridView);
if (virtualizingStackPanel != null && pageState != null) { pageState["virtualizingStackPanelHorizontalOffset"] = virtualizingStackPanel.HorizontalOffset; }}
protected override void LoadState(object navigationParameter, System.Collections.Generic.Dictionary<string, object>
pageState){ if (pageState != null && pageState.ContainsKey("virtualizingStackPanelHorizontalOffset")) { double.TryParse(pageState["virtualizingStackPanelHorizontalOffset"].ToString(), out virtualizingStackPanelHorizontalOffset); }}
LoadState & SaveState: SuspensionManager
<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="ApplicationViewStates"> <VisualState x:Name="FullScreenLandscape"/> <VisualState x:Name="Filled"/> <VisualState x:Name="FullScreenPortrait"> <Storyboard> ... </Storyboard> </VisualState> <VisualState x:Name="Snapped"> <Storyboard> ... </Storyboard> </VisualState> </VisualStateGroup></VisualStateManager.VisualStateGroups>
6. Support visual state for landscape, portrait, fill, and snap
World Ready
7. Separate resources for each locale
<ToolTip x:Uid=“PreviewCartoonizeAppBarButtonToolTip” Content=“Preview Cartoonization” … />
Model-View-ViewModel Pattern
View First:this.Frame.Navigate(typeof(ItemDetailPage), itemId);
ViewModel First:Var itemDetailPageViewModel = new ItemDetailPageViewModel(…)
{ ItemId = itemId };navigationService.Navigate(itemDetailPageViewModel);
8. Navigation: View or ViewModel First
Nicki says: Neither!
String based navigation, like
URL’s!navigationService.Navigate( “ItemDetails”, itemId);
public abstract class BindableBase : INotifyPropertyChanged{ public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null) { if (object.Equals(storage, value)) return false; storage = value; this.OnPropertyChanged(propertyName); return true; }
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { var eventHandler = this.PropertyChanged; if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); } }}
9. Use BindableBase class to provide INPC
10. Use the Kona ViewModelLocator• Convention based lookup
• MyNamespace.MyPage -> MyNamespace.MyPageViewModel• Ability to override convention with exceptions to rule• Can leverage container to instantiate ViewModels.
XAML (attached property):konaInfrastructure:ViewModelLocator.AutoWireViewModel="true"
Typical Validation in WPF/Silverlight
• Implement INotifyDataErrorInfo• UI controls bind to errors dictionary if
NotifyOnValidationError=True
<TextBox Text="{Binding Id, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}"/>
View:<TextBox
Text="{Binding Address.FirstName, Mode=TwoWay}" behaviors:HighlightFormFieldOnErrors.PropertyErrors="{Binding Errors[FirstName]}" />
ViewModel:_bindableValidator = new BindableValidator(_address);
public BindableValidator Errors{ get { return _bindableValidator; }}
11. Use Kona BindableValidator
Decoupled Eventing• Hollywood Parent style UI
Composition (user control)• Child control needs to listen to
events raised by long lived services but no way to unhook…
• Ported Prism EventAggregator
12. Use EventAggregator when necessarypublic SubscriberViewModel(IEventAggregator eventAggregator){ eventAggregator.GetEvent<ShoppingCartUpdatedEvent>()
.Subscribe(s => UpdateItemCountAsync());}
public PublisherViewModel(IEventAggregator eventAggregator){ _eventAggregator = eventAggregator;}
_eventAggregator.GetEvent<ShoppingCartUpdatedEvent>().Publish(string.Empty);
Commanding vs ViewModel Method InvocationICommand:
void Execute(object)bool CanExecute(object)event EventHandler CanExecuteChanged
Command Invoker:ButtonBase
-----------------------------------------------------Event -> Action
13. Use DelegateCommand for controls that support ICommandView:<Button Content=“Go to shopping cart” Command="{Binding ShoppingCartNavigationCommand}" />
ViewModel:ShoppingCartNavigationCommand = new DelegateCommand(NavigateToShoppingCartPage,
CanNavigateToShoppingCartPage);
ShoppingCartNavigationCommand.RaiseCanExecuteChanged();
14. Use AttachedBehaviors and Actions for the restView:<GridView x:Name="itemGridView“
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplate="{StaticResource KonaRI250x250ItemTemplate}"SelectionMode="None“ IsItemClickEnabled="True"behaviors:ListViewItemClickedToAction.Action=
"{Binding CategoryNavigationAction}">
ViewModel:CategoryNavigationAction = NavigateToCategory;
Suspend, Resume, and Terminate
Symposium 2013
15. Use Kona RestorableStateAttribute and MVVM frameworkpublic class MyViewModel : ViewModel, INavigationAware{ private string _name;
[RestorableState] public string Name
{ get { return _name; } set { SetProperty(ref _name, value); } }}
16. Unit Testing nicely integrated into VS2012
WP7: Jeff Wilcox's Silverlight Unit Test Framework• Tests run in emulator or device
Unit Test Library (Windows Store apps)• Run and debug from IDE• Can run tests from command line and export as trx format.
<ItemGroup> <TestAppPackages Include="$(MSBuildProjectDirectory)\..\Source\**\*.appx" /></ItemGroup> <Target Name="Test"> <Exec ContinueOnError="true" Command="vstest.console.exe /InIsolation /logger:trx %(TestAppPackages.Identity)" /></Target>
Symposium 2013
17. File System Local Data (SQLite)
Roaming Data
Hi Priority Roaming Data
Password Vault
Symposium 2013
Thanks! http://konaguidance.codeplex.com