370 likes | 628 Views
Tips for building a Windows Store app using XAML and C#: The Kona project. Francis Cheung fcheung@microsoft.com . Agenda. Kona C# Background Tips and Lessons Learned for building C# Windows Store apps. Prism for WPF, Silverlight and Windows Phone. Modularity UI Composition
E N D
Tips for building a Windows Store app using XAML and C#: The Kona project Francis Cheung fcheung@microsoft.com
Agenda • Kona C# Background • Tips and Lessons Learned for building C# Windows Store apps
Prism for WPF, Silverlight and Windows Phone • Modularity • UI Composition • Region Navigation • Decoupled Communication • Commands • MVVM Support
The Kona Project 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
Rethink Prism Scenarios for Windows Store • Modularity • UI Composition • Region Navigation • Decoupled Communication • Commands • MVVM Support ? ?
Demo AdventureWorks Shopper • Walkthrough
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)
4. async & await are your friends 1: asyncTask<int>AccessTheWebAsync() 2: { 3: HttpClient client = new HttpClient(); 4: Task<string>getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); 5: DoIndependentWork(); 6: 7: string urlContents = awaitgetStringTask; 8: return urlContents.Length; 9: }
5. Use the LayoutAwarePage class to provide navigation, state management, and visual state management Navigation support protected 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 switching public void StartLayoutUpdates(object sender, RoutedEventArgs e) public void StopLayoutUpdates(object sender, RoutedEventArgs e) Process lifetime management protected 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)
Navigation & Visual State Support XAML: <Button Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResourceBackButtonStyle}"/> <UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
LoadState & SaveState: SuspensionManager protected override void SaveState(System.Collections.Generic.Dictionary<string, object> pageState){varvirtualizingStackPanel = 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); }}
6. Support visual state for landscape, portrait, fill, and snap <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>
7. Separate resources for each locale <ToolTip x:Uid=“PreviewCartoonizeAppBarButtonToolTip” Content=“Preview Cartoonization” … />
8. Navigation: View or ViewModel First View First:this.Frame.Navigate(typeof(ItemDetailPage), itemId); ViewModel First: VaritemDetailPageViewModel = new ItemDetailPageViewModel(…) { ItemId = itemId };navigationService.Navigate(itemDetailPageViewModel);
Neither! String based navigation, like URL’s! Nicki says: navigationService.Navigate( “ItemDetails”, itemId);
9. Use BindableBase class to provide INPC public abstract class BindableBase : INotifyPropertyChanged{ public event PropertyChangedEventHandlerPropertyChanged; protected boolSetProperty<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) {vareventHandler = this.PropertyChanged; if (eventHandler != null) {eventHandler(this, new PropertyChangedEventArgs(propertyName)); } }}
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}"/>
11. Use Kona BindableValidator View: <TextBox Text="{Binding Address.FirstName, Mode=TwoWay}" behaviors:HighlightFormFieldOnErrors.PropertyErrors="{Binding Errors[FirstName]}" /> ViewModel: _bindableValidator = new BindableValidator(_address); public BindableValidatorErrors{get { return _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 necessary public SubscriberViewModel(IEventAggregatoreventAggregator){eventAggregator.GetEvent<ShoppingCartUpdatedEvent>() .Subscribe(s => UpdateItemCountAsync());} public PublisherViewModel(IEventAggregatoreventAggregator){ _eventAggregator = eventAggregator;} _eventAggregator.GetEvent<ShoppingCartUpdatedEvent>() .Publish(string.Empty);
Commanding vsViewModel Method Invocation ICommand: void Execute(object) boolCanExecute(object) event EventHandlerCanExecuteChanged Command Invoker: ButtonBase ----------------------------------------------------- Event -> Action
13. Use DelegateCommand for controls that support ICommand View: <Button Content=“Go to shopping cart” Command="{Binding ShoppingCartNavigationCommand}" /> ViewModel: ShoppingCartNavigationCommand = new DelegateCommand(NavigateToShoppingCartPage, CanNavigateToShoppingCartPage); ShoppingCartNavigationCommand.RaiseCanExecuteChanged();
14. Use AttachedBehaviors and Actions for the rest View: <GridView x:Name="itemGridView“ ItemsSource="{Binding Source={StaticResourcegroupedItemsViewSource}}" ItemTemplate="{StaticResource KonaRI250x250ItemTemplate}" SelectionMode="None“ IsItemClickEnabled="True" behaviors:ListViewItemClickedToAction.Action= "{Binding CategoryNavigationAction}"> ViewModel: CategoryNavigationAction = NavigateToCategory;
15. Use Kona RestorableStateAttribute and MVVM framework public 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> <TestAppPackagesInclude="$(MSBuildProjectDirectory)\..\Source\**\*.appx" /> </ItemGroup> <TargetName="Test"> <ExecContinueOnError="true"Command="vstest.console.exe /InIsolation /logger:trx %(TestAppPackages.Identity)" /></Target>
17. File System • Local Data (SQLite) • Roaming Data • Hi Priority Roaming Data • Password Vault
Thanks! • http://konaguidance.codeplex.com • fcheung@microsoft.com