netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8
-
Upload
netmind -
Category
Technology
-
view
1.695 -
download
0
description
Transcript of netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8
F O C U S Q U A L I T Y E X P E R I E N C E
Barcelona, Noviembre 2012
Xavier Saladié
Desarrollo Windows 8
Desarrollo Windows 8
Plataforma Aplicaciones Windows 8
Tools
UI Controls
Appbar
FlipView
ListView, Grouping y Semantic zoom
Contratos
Notificaciones
Puntos claves para publicar en el Store
Contenidos
Co
re O
S
Broker
Llamadas Directas
Llamadas Delegadas
Contenedor+ Código Firmado y Verificado
Tu aplicación
WinRT APIs
Process.exe (C#,VB.Net, C++)
o
WWAHost.exe (HTML/JS)
AppXManifest
La app toma 5s para
entrar en suspensión
La App no es
notificada antes de
terminarse
Las apps son informadas
cuando se las ha reanudado
Usuario
Lanza
App
Pantalla
Splash
Local
Storage
La información se
sincroniza desde la
cuenta Microsoft del
usuario
• App usan sus datos y los almacena localmente
The development tools are FREE!
If you use a higher SKU, it just works!
AppXManifest.xml
BlockMap
Signature
Zip Central
Directory
Files / Assets
.appx package
Visual Studio 2012
Clear Button Spell Checking
Reveal Button
<!– Paso 1: declarar el control -->
<div id=“list” data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'none' }"></div>
/* Paso 2: Llamar a WinJS.UI.processAll() */
/* Paso 3: Usar el control */
document.getElementById(‘list’).winControl.addEventListener (‘selectionchanged’, onSelChanged );
<Page
x:Class="CSharpWinRT.BlankPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CSharpWinRT"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Button Content="La caja de Pandora" Click="Button_Click_1" Height="81" Margin="0,365,0,322" Width="248" HorizontalAlignment="Center" FontWeight="Normal" FontSize="22" />
<Image x:Name="selectedImage" Width="600" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Margin="383,384,383,383" > </Image>
</Grid>
</Page>
Se utiliza para mostrar las acciones de una ventana.
Se mantiene oculta.
Puede cambiar en función de la pantalla.
Se activa con el botón derecho
Iconos: http://msdn.microsoft.com/en-us/library/windows/apps/hh770557.aspx
<Page.BottomAppBar> <AppBar x:Name="BottomAppBar1" Padding="10,0,10,0" AutomationProperties.Name="Bottom App Bar"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="50*"/> <ColumnDefinition Width="50*"/> </Grid.ColumnDefinitions> <StackPanel x:Name="LeftPanel" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left"> <Button x:Name="Edit" Style="{StaticResource EditAppBarButtonStyle}" Tag="Edit"/> <Button x:Name="Save" Style="{StaticResource SaveAppBarButtonStyle}" Tag="Save"/> <Button x:Name="Delete" Style="{StaticResource DeleteAppBarButtonStyle}" Tag="Delete"/> </StackPanel> <StackPanel x:Name="RightPanel" Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right"> <Button x:Name="Refresh" Style="{StaticResource RefreshAppBarButtonStyle}" Tag="Refresh"/> <Button x:Name="Previous" Style="{StaticResource PreviousAppBarButtonStyle}" Tag="Previous"/> <Button x:Name="Next" Style="{StaticResource NextAppBarButtonStyle}" Tag="Next"/> <Button x:Name="Help" Style="{StaticResource HelpAppBarButtonStyle}" Tag="Help"/> </StackPanel> </Grid> </AppBar> </Page.BottomAppBar>
public MyPage() { this.InitializeComponent(); Back.Click += Back_Click; } private void Back_Click(object sender, RoutedEventArgs e) { if (this.Frame.CanGoBack) { Frame.GoBack(); } }
Muestra una colección de elementos.
Genera un avance y retroceso por defecto.
Se pueden utilizar plantillas para el contenido.
<FlipView x:Name="flipView1" Width="480" Height="270" BorderBrush="Black" BorderThickness="1"> <FlipView.ItemTemplate> <DataTemplate> <Grid> <Image Width="480" Height="270" Source="{Binding Image}" Stretch="UniformToFill"/> <Border Background="#A5000000" Height="80" VerticalAlignment="Bottom"> <TextBlock Text="{Binding Name}" FontFamily="Segoe UI" FontSize="26.667" Foreground="#CCFFFFFF" Padding="15,20"/> </Border> </Grid> </DataTemplate> </FlipView.ItemTemplate> </FlipView>
Permite mostrar listados de información.
Hace uso de plantillas para configurar el contenido.
<ListView x:Name="ItemListView" Width="Auto" Height="Auto" HorizontalAlignment="Left" Background="{StaticResource ApplicationPageBackgroundThemeBrush}" ItemTemplate="{StaticResource StoreFrontTileTemplate}" ItemContainerStyle="{StaticResource StoreFrontLVTileStyle}" BorderBrush="LightGray" BorderThickness="1" VerticalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" SelectionMode="None"/>
<!– List View Resources --> <DataTemplate x:Key="StoreFrontTileTemplate"> <Grid HorizontalAlignment="Left" Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Orientation="Horizontal" Margin="10,10,0,0"> <Image Source="{Binding Image}" Height="60" Width="60" VerticalAlignment="Center" Margin="0,0,10,0"/> <StackPanel Margin="0,0,0,0" Orientation="Vertical"> <TextBlock TextWrapping="Wrap" Foreground="{StaticResource ApplicationForegroundThemeBrush}" Style="{StaticResource ItemTitleStyle}" Width="200“ VerticalAlignment="Center" Text="{Binding Title}" HorizontalAlignment="Left" FontFamily="Segoe UI" /> <TextBlock TextWrapping="Wrap" Foreground="{StaticResource ApplicationForegroundThemeBrush}" Style="{StaticResource ItemSubtitleStyle}“
Width="200" MaxHeight="20" VerticalAlignment="Center" Text="{Binding Category}" HorizontalAlignment="Left"/> </StackPanel> </StackPanel> </Grid> </DataTemplate> <Style x:Key="StoreFrontLVTileStyle" TargetType="ListViewItem"> <Setter Property="FontFamily" Value="Segoe UI" /> <Setter Property="Height" Value="80" /> <Setter Property="Width" Value="292" /> <Setter Property="Padding" Value="0" /> <Setter Property="Margin" Value="0,0,8,8" /> <Setter Property="HorizontalContentAlignment" Value="Left" /> <Setter Property="VerticalContentAlignment" Value="Top" /> <Setter Property="BorderThickness" Value="0"/> <Setter Property="TabNavigation" Value="Local" /> </Style>
Nos permite agrupar la información.
La forma de crear grupos es personalizada.
Se utiliza el control ListView como base.
<Page.Resources> <CollectionViewSource x:Name="cvs1" IsSourceGrouped="true" /> </Page.Resources> <GridView x:Name="ItemsByCategory" VerticalAlignment="Bottom" ItemsSource="{Binding Source={StaticResource cvs1}}" BorderBrush="{StaticResource ApplicationForegroundThemeBrush}" BorderThickness="1"> <GridView.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.ItemTemplate> <DataTemplate> <Grid HorizontalAlignment="Left" Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Orientation="Horizontal" Margin="10,10,0,0"> <Image Source="{Binding Image}" Height="60" Width="60" VerticalAlignment="Center" Margin="0,0,10,0"/> <StackPanel Margin="0,0,0,0" Orientation="Vertical"> <TextBlock TextWrapping="Wrap" Width="200" VerticalAlignment="Center" Text="{Binding Title}" HorizontalAlignment="Left" FontFamily="Segoe UI" /> </StackPanel> </StackPanel> </Grid> </DataTemplate> </GridView.ItemTemplate> <GridView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" Margin="0"> <TextBlock Text='{Binding Key}' Foreground="Gray" FontSize="25" Margin="5" /> </Grid> </DataTemplate> </GroupStyle.HeaderTemplate> <GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid Orientation="Vertical" Height="400" /> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </GridView.GroupStyle> </GridView>
internal List<GroupInfoList<object>> GetGroupsByCategory() { List<GroupInfoList<object>> groups = new List<GroupInfoList<object>>(); var query = from item in Collection orderby ((Item)item).Category group item by ((Item)item).Category into g select new { GroupName = g.Key, Items = g }; foreach (var g in query) { GroupInfoList<object> info = new GroupInfoList<object>(); info.Key = g.GroupName; foreach (var item in g.Items) { info.Add(item); } groups.Add(info); } return groups; }
public class GroupInfoList<T> : List<object> { public object Key { get; set; } public new IEnumerator<object> GetEnumerator() { return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();} }
List<GroupInfoList<object>> dataCategory = _storeData.GetGroupsByCategory(); cvs1.Source = dataCategory;
<Grid x:Name="ContentPanel" VerticalAlignment="Top" HorizontalAlignment="Left"> <SemanticZoom x:Name="semanticZoom" VerticalAlignment="Bottom"> <SemanticZoom.ZoomedOutView> <GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False"> <GridView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Group.Key}" FontFamily="Segoe UI Light" FontSize="24"/> </DataTemplate> </GridView.ItemTemplate> <GridView.ItemsPanel> <ItemsPanelTemplate> <WrapGrid ItemWidth="75" ItemHeight="75" MaximumRowsOrColumns="1“ VerticalChildrenAlignment="Center" /> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="Margin" Value="4" /> <Setter Property="Padding" Value="10" /> <Setter Property="BorderBrush" Value="Gray" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> </Style> </GridView.ItemContainerStyle> </GridView> </SemanticZoom.ZoomedOutView> List<GroupInfoList<object>> dataLetter = _storeData.GetGroupsByLetter();
cvs2.Source = dataLetter; (semanticZoom.ZoomedOutView as ListViewBase).ItemsSource = cvs2.View.CollectionGroups;
<SemanticZoom.ZoomedInView> <GridView ItemsSource="{Binding Source={StaticResource cvs2}}" IsSwipeEnabled="True" ScrollViewer.IsHorizontalScrollChainingEnabled="False"> <GridView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="10,10,0,0" HorizontalAlignment="Left" Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Image Source="{Binding Image}" Height="60" Width="60" VerticalAlignment="Center" Margin="0,0,10,0"/> <TextBlock TextWrapping="Wrap" Foreground="{StaticResource ApplicationForegroundThemeBrush}" Width="200“ VerticalAlignment="Center“ Text="{Binding Title}" HorizontalAlignment="Left" FontFamily="Segoe UI" /> </StackPanel> </DataTemplate> </GridView.ItemTemplate> <GridView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <TextBlock Text='{Binding Key}' Foreground="{StaticResource ApplicationForegroundThemeBrush}" Margin="5" FontSize="18“ FontFamily="Segoe UI Light" /> </DataTemplate> </GroupStyle.HeaderTemplate> <GroupStyle.ContainerStyle> <Style TargetType="GroupItem"> <Setter Property="Template"> ….
//override in app the handler to OnWindowCreated protected override void OnWindowCreated(WindowCreatedEventArgs args) { // Register QuerySubmitted handler for the window at window creation time SearchPane.GetForCurrentView().QuerySubmitted += new TypedEventHandler<SearchPane, SearchPaneQuerySubmittedEventArgs>(OnQuerySubmitted);}
private void OnQuerySubmitted(SearchPane sender, SearchPaneQuerySubmittedEventArgs args) { // Process the query if (MainPage.Current != null) { MainPage.Current.ProcessQueryText(args.QueryText);} }
protected override void OnNavigatedTo(NavigationEventArgs e) { // Register the current page as a share source. this.dataTransferManager = DataTransferManager.GetForCurrentView(); this.dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested); } protected override void OnNavigatedFrom(NavigationEventArgs e) { // Unregister the current page as a share source. this.dataTransferManager.DataRequested -= new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested); } // When share is invoked the event handler will be called to populate the datapackage. private void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs e) { bool succeeded = false; string dataPackageText = TextToShare.Text; if (!String.IsNullOrEmpty(dataPackageText)) { DataPackage requestData = e.request.Data; requestData.Properties.Title = TitleInputBox.Text; requestData.Properties.Description = DescriptionInputBox.Text; requestData.SetText(dataPackageText); succeeded = true; } else { e.request.FailWithDisplayText("Enter the text you would like to share and try again."); } return succeeded; }
Permite recibir información de otras apps.
Puede permitir distintos formatos.
Se activa al seleccionar la app dentro de Share.
//On App we override the event for Share Targeting Activated and navigate to the Page receiving data protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args) { var rootFrame = new Frame(); rootFrame.Navigate(typeof(MainPage), args.ShareOperation); Window.Current.Content = rootFrame; Window.Current.Activate(); }
//On NavigateTo event of the page receiving data, we just do it asynchronously protected override async void OnNavigatedTo(NavigationEventArgs e) { // It is recommended to only retrieve the ShareOperation object in the activation handler, return as // quickly as possible, and retrieve all data from the share target asynchronously. this.shareOperation = (ShareOperation)e.Parameter; await Task.Factory.StartNew(async () => { // Retrieve the data package properties. this.sharedDataTitle = this.shareOperation.Data.Properties.Title; this.sharedDataDescription = this.shareOperation.Data.Properties.Description; this.sharedThumbnailStreamRef = this.shareOperation.Data.Properties.Thumbnail; this.shareQuickLinkId = this.shareOperation.QuickLinkId; // Retrieve the data package content. if (this.shareOperation.Data.Contains(StandardDataFormats.Uri)) { // The GetUriAsync() API will throw if there was an error retrieving data. try { this.sharedUri = await this.shareOperation.Data.GetUriAsync(); } catch (Exception ex) { … } }
Square (1x1) Wide (2x1)
IWideTileNotificationContent tileContent = null; ITileWideImageAndText01 wideContent = TileContentFactory.CreateTileWideImageAndText01(); wideContent.RequireSquareContent = false; wideContent.TextCaptionWrap.Text = "The image is in the appx package"; wideContent.Image.Src = "ms-appx:///images/redWide.png"; wideContent.Image.Alt = "Red image"; tileContent = wideContent; // Users can resize tiles to square or wide. // Apps can choose to include only square assets (meaning the app's tile can never be wide), or // include both wide and square assets (the user can resize the tile to square or wide). // Apps cannot include only wide assets. Apps that support being wide should include square tile // notifications since users determine the size of the tile. // create the square template and attach it to the wide template ITileSquareText04 squareContent = TileContentFactory.CreateTileSquareText04(); squareContent.TextBodyWrap.Text = "Hello World! My very own tile notification"; tileContent.SquareContent = squareContent; TileUpdateManager.CreateTileUpdaterForApplication().Update(tileContent.CreateNotification());
http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh868255(v=win.10).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh868255(v=win.10).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh868255(v=win.10).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh868255(v=win.10).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh868255(v=win.10).aspx
http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh868255(v=win.10).aspx
Permite añadir segundos accesos a una app.
El usuario siempre debe aprobar este segundo tile.
Es posible actualizar su contenido.
// Prepare package images for use as the Tile Logo and small Logo in our tile to be pinned Uri logo = new Uri("ms-appx:///Assets/squareTile-sdk.png"); Uri smallLogo = new Uri("ms-appx:///Assets/smallTile-sdk.png"); // In this sample, we'll pass in the date and time the secondary tile was pinned. public const string SecTileId = "SecondaryTileId" string tArguments = SecTileId + " WasPinnedAt=" + DateTime.Now.ToLocalTime().ToString(); // Create a 1x1 Secondary tile SecondaryTile secTile = new SecondaryTile(SecTileId, "Title text", "Name when searching", tArguments, TileOptions.ShowNameOnLogo, logo); secTile.ForegroundText = ForegroundText.Dark; secTile.SmallLogo = smallLogo; // OK, the tile is created and we can now attempt to pin the tile. bool isPinned = await SecTile.RequestCreateForSelectionAsync( MainPage.GetElementRect((FrameworkElement)sender),Windows.UI.Popups.Placement.Below);
// Typical OnLaunched override Method of App.xaml.cs async protected override void OnLaunched(LaunchActivatedEventArgs args) { if (args.PreviousExecutionState == ApplicationExecutionState.Terminated) { // Do an asynchronous restore await RestoreData() } if (Window.Current.Content == null) { var rootFrame = new Frame(); rootFrame.Navigate(typeof(MainPage)); ((MainPage)rootFrame.Content).LaunchArgs = args; Window.Current.Content = rootFrame; } else { if (args.Arguments != “”) { //Inspect content of args and navigate where is needed } } Window.Current.Activate(); }
IToastNotificationContent toastContent = null; IToastImageAndText03 templateContent = ToastContentFactory.CreateToastImageAndText03(); templateContent.TextHeadingWrap.Text = "Heading text that wraps"; templateContent.TextBody.Text = "Body text"; templateContent.Image.Src = "images/toastImageAndText.png"; templateContent.Image.Alt = "Placeholder image"; toastContent = templateContent; // Set the launch activation context parameter on the toast. toastContent.Launch = "Context123"; // Create a toast from content ToastNotification toast = toastContent.CreateNotification(); // create a ToastNotifier object to show the toast ToastNotificationManager.CreateToastNotifier().Show(toast);
// In app.OnLaunched and in app.OnSearchActivated we register event for managing settings // Register handler for CommandsRequested events from the settings pane SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested; void OnCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args) { // Add an About command var about = new SettingsCommand("about", "About", (handler) => { var settings = new SettingsFlyout(); settings.Content = new AboutUserControl(); settings.HeaderBrush = new SolidColorBrush(_background); settings.Background = new SolidColorBrush(_background); settings.HeaderText = "About"; settings.IsOpen = true; }); args.Request.ApplicationCommands.Add(about); // Add a Preferences command var preferences = new SettingsCommand("preferences", "Preferences", (handler) => { var settings = new SettingsFlyout(); settings.Content = new PreferencesUserControl(); settings.HeaderBrush = new SolidColorBrush(_background); settings.Background = new SolidColorBrush(_background); settings.HeaderText = "Preferences"; settings.IsOpen = true; }); args.Request.ApplicationCommands.Add(preferences); }
<UserControl x:Class="ContosoCookbook.PreferencesUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:ContosoCookbook" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid> <ToggleSwitch x:Name="Remember" Header="Remember where I was" Toggled="OnToggled" /> </Grid> </UserControl>
private void Button_Click(object sender, RoutedEventArgs e) { Flyout flyOut = new Flyout(); flyOut.PlacementTarget = sender as UIElement; flyOut.Placement = PlacementMode.Top; flyOut.Content = new FlyoutUserControl(); flyOut.IsOpen = true; }
// Create the message dialog and set its content and title var msgDlg = new MessageDialog(“Updates found. Would you like to install?", "Updates"); // Add commands and set their callbacks msgDlg.Commands.Add(new UICommand("Don't install", (command) => { rootPage.NotifyUser("'Don't install' command has been selected.", NotifyType.StatusMessage); })); msgDlg.Commands.Add(new UICommand("Install updates", (command) => { rootPage.NotifyUser("'Install updates' command has been selected.", NotifyType.StatusMessage); })); // Set the command that will be invoked by default msgDlg.DefaultCommandIndex = 1; // Show the message dialog await msgDlg .ShowAsync();
Escenario Deberías….
using Windows.Networking.Connectivity;
...
public static bool isConnected()
{ var p=NetworkInformation.GetInternetConnectionProfile();
if (p!=null) {
if (p.GetNetworkConnectivityLevel()==NetworkConnectivityLevel.InternetAccess)
{ return true }
else
{ return false; } }
else { return false; } }
121
Anuncia con Microsoft Advertising o tu ad vendor
favorito
Y para terminar…
Foros en español
http://social.msdn.microsoft.com/Forums/es-ES/w8metroes/
Foros en inglés
http://social.msdn.microsoft.com/Forums/en-US/category/windowsapps
Alias de Soporte Desarrollo Windows 8
Introducción al desarrollo de aplicaciones Metro para Windows 8
http://blogs.msdn.com/b/esmsdn/archive/2012/07/18/introducci-243-n-al-desarrollo-de-aplicaciones-metro-para-windows-8.aspx
Cursos de Formación de Windows 8
http://blogs.msdn.com/b/esmsdn/archive/2012/09/04/cursos-de-formaci-243-n-de-windows-8.aspx
Tips & Tricks de desarrollo para Windows 8
http://blogs.msdn.com/b/esmsdn/archive/2012/08/08/tips-amp-tricks-de-desarrollo-para-windows-8.aspx
Windows 8 Metro style app samples
http://code.msdn.microsoft.com/windowsapps
Problemas comunes para pasar la certificación de Windows 8
http://blogs.msdn.com/b/esmsdn/archive/2012/07/31/problemas-comunes-para-pasar-la-certificaci-243-n-de-windows-8.aspx
V3.0 Certification requirements
http://msdn.microsoft.com/en-us/library/windows/apps/jj128432.aspx
F O C U S Q U A L I T Y E X P E R I E N C E
Preguntas y aclaraciones
Muchas gracias por su atención Xavier Saladié