Professional Documents
Culture Documents
Windows 10
Universal Windows Platform (UWP)
I. CONTROLES.............................................................................................................................................. 3
1. RELATIVEPANEL .............................................................................................................................................. 3
2. SPLITVIEW ..................................................................................................................................................... 5
a. SplitView de base et Adaptive Triggers ................................................................................................. 5
b. Bouton Rechercher et AutoSuggestBox dans SplitView ......................................................................... 8
c. Page Header : Contrle utilisateur Barre de titre avec marge adaptable selon le mode
daffichage du SplitView ............................................................................................................................... 10
3. NAVIGATION MODEL...................................................................................................................................... 13
4. BACKBUTTON............................................................................................................................................... 16
5. COMMANDBAR, SYMBOLICON, .................................................................................................................... 17
6. MEDIA ELEMENT ET CUSTOM MEDIA TRANSPORT CONTROLS ................................................................................. 20
7. CONTENT DIALOG ......................................................................................................................................... 21
8. AUTOSUGGESTBOX ( REMPLAANT DE SEARCHBOX )....................................................................................... 22
9. POPUP ........................................................................................................................................................ 23
10. EXTENDED SPASHSCREEN ........................................................................................................................... 23
11. VARIABLESIZEDWRAPGRID......................................................................................................................... 25
II. ACCENT ET THEME (DARK, LIGHT) .......................................................................................................... 27
DFINIR SON PROPRE THME .................................................................................................................................... 27
III. DESIGN TIME.......................................................................................................................................... 28
IV. DATATEMPLATESELECTOR ................................................................................................................. 29
DERNIER ELEMENT AFFICHER PLUS POUR LISTVIEW OU GRIDVIEW .................................................................... 31
V. HEADERGROUP ...................................................................................................................................... 34
DATATEMPLATES ........................................................................................................................................... 36
POUR LISTVIEW..................................................................................................................................................... 36
POUR GRIDVIEW ................................................................................................................................................... 38
VI. ADAPTIVE UI ...................................................................................................................................... 40
1. ADAPTIVE TRIGGERS ...................................................................................................................................... 41
2. MASTER DETAILS................................................................................................................................................ 43
3. CUSTOM ADAPTIVE TRIGGERS .......................................................................................................................... 45
4. DEVICEFAMILY ............................................................................................................................................. 48
5. ASTUCE : REACTIVER LES ANIMATIONS, TRANSITIONS WINDOWS ............................................................................ 48
VII. X :BIND COMPILED BINDING ........................................................................................................ 49
1. BINDING DE COLLECTION ................................................................................................................................ 49
2. AVEC DATATEMPLATE.................................................................................................................................... 50
3. AVEC DICTIONNAIRE DE RESSOURCES (RESOURCEDICTIONARY) ............................................................................... 50
4. RELATIVESOURCE ET ELEMENTNAME LIER AU NOM DE LELEMENT ........................................................... 51
5. SOURCE ET DATACONTEXT .. AJOUTER UNE PROPRIETE DU VIEWMODEL DANS LE CODE-BEHIND ....................... 51
6. BINDING EVENTS .......................................................................................................................................... 52
7. DEFER LOADING ............................................................................................................................................ 53
2
Avec Windows 10, le modle dapplication universelle permet de crer partir dun seul projet une
application pour le Windows Store (PC, tablettes et ordinateurs portables) et une application pour le
Windows Phone Store.
I. Contrles
Liste des contrles et exemples
1. RelativePanel
Permet de positionner les lments les uns par rapport aux autres et de grer le repositionnement
des lments avec des AdaptiveTriggers.
Proprits de placement
Plus
AlignHorizontalCenterWith
AlignVerticalCenterWith
AlignBottomWith
AlignTopWith
AlignLeftWith
AlignRightWith
Exemple
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Rectangle x:Name="rectangle1" Fill="Red" Width="300" Height="150" />
<Rectangle x:Name="rectangle2" Fill="Blue" RelativePanel.RightOf="rectangle1" Width="300"
Height="150" />
<Rectangle x:Name="rectangle3" Fill="Green" RelativePanel.Below="rectangle2"
RelativePanel.AlignHorizontalCenterWith="rectangle2" Width="300" Height="150" />
</RelativePanel>
AlignHorizontalCenterWithPanel
AlignVerticalCenterWithPanel
2. SplitView
a. SplitView de base et Adaptive Triggers
<SplitView>
<SplitView.Pane>
<!-- menu -->
</SplitView.Pane>
<SplitView.Content>
<!-- content-->
</SplitView.Content>
</SplitView>
Exemple
De 720 1024,
CompactInline et
panel ferm
DisplayMode
SplitView
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup> Adaptive Triggers, on
<VisualState x:Name="VisualStateMin0"> change le mode
<VisualState.StateTriggers> daffichage du splitview
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
selon la taille de la page
<VisualState.Setters>
<Setter Target="splitView.DisplayMode" Value="Overlay"/>
<Setter Target="splitView.IsPaneOpen" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateMin720">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="splitView.DisplayMode" Value="CompactInline"/>
<Setter Target="splitView.IsPaneOpen" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateMin1024">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1024" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="splitView.DisplayMode" Value="CompactInline"/>
<Setter Target="splitView.IsPaneOpen" Value="True"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SplitView x:Name="splitView"
DisplayMode="CompactInline" Marge de 48 par rapport au top
IsPaneOpen="True" pour laisser la place au bouton
OpenPaneLength="320">
<SplitView.Pane> hamburger
<ListView Margin="0,48,0,0"
VerticalAlignment="Stretch"
ItemsSource="{x:Bind ViewModel.MenuItems}"
ItemTemplate="{StaticResource MenuItemTemplate}"
SelectionMode="None"
IsItemClickEnabled="True"/>
</SplitView.Pane> On peut dfinir ce que lon veut en contenu .De
plus on peut omettre SplitView.Content
<SplitView.Content>
<Frame x:Name="mainFrame"></Frame>
</SplitView.Content> Bouton hamburger
</SplitView> plac en dernier
Template
<DataTemplate x:Key="MenuItemTemplate" x:DataType="local:MenuItem">
<StackPanel Orientation="Horizontal" Margin="2,0,0,0">
<SymbolIcon Symbol="{x:Bind Symbol}"/>
<TextBlock Text="{x:Bind Title}" Margin="24,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
Code-behind
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
ViewModel = new MainPageViewModel();
}
On remplit la collection
public class MainPageViewModel
{
public ObservableCollection<MenuItem> MenuItems { get; set; }
public MainPageViewModel()
{
MenuItems = new ObservableCollection<MenuItem>();
MenuItems.Add(new MenuItem("Accueil", Symbol.Home));
MenuItems.Add(new MenuItem("Vidos", Symbol.Video));
MenuItems.Add(new MenuItem("Musiques", Symbol.Audio));
}
}
8
<SplitView x:Name="splitView"
DisplayMode="CompactInline" On fait en sorte que chaque
IsPaneOpen="True"
OpenPaneLength="320"> lment fasse 48px de haut
<SplitView.Pane>
<StackPanel Margin="0,48,0,0"> On lie la visibilit de
<Grid Height="48">
lAutoSuggestBox et du bouton
<AutoSuggestBox x:Name="autoSuggestBox"
Margin="12,0" rechercher SplitView
PlaceholderText="Rechercher" IsPaneOpen et on utilise des
VerticalAlignment="Center" converters
QueryIcon="Find"
Visibility="{Binding IsPaneOpen, Converter={StaticResource
BooleanToVisibilityConverter}, ElementName=splitView}" />
<Button x:Name="searchButton"
Style="{StaticResource Square48x48ButtonStyle}"
Visibility="{Binding IsPaneOpen, Converter={StaticResource
BooleanToCollapsedConverter}, ElementName=splitView}"
Click="searchButton_Click">
<SymbolIcon Symbol="Find" />
</Button>
</Grid>
c. Page Header : Contrle utilisateur Barre de titre avec marge adaptable selon le
mode daffichage du SplitView
Cration dun UserControl PageHeader qui pourra tre gliss sur chaque page de contenu
(affiche dans la zone de contenu du SplitView) . On pourra personnaliser le contenu de cette barre
de titre pour chaque page, mais surtout permettra de grer la marge entre le titre et le bouton
hamburger du splitview. En effet, en mode daffichage Overlay, le titre (sil est align gauche) et le
bouton hamburger risqueraient de se chevaucher, il faut donc grer la marge.
<UserControl
x:Class="UWPNavigationDemo.Controls.PageHeader"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWPNavigationDemo.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Hauteur de 48 pour tre align avec
Height="48"
d:DesignHeight="300" le bouton hamburger
d:DesignWidth="400">
<Grid>
<Grid x:Name="titleBar">
<ContentPresenter x:Name="content"
VerticalAlignment="{x:Bind VerticalContentAlignment}"
HorizontalAlignment="{x:Bind HorizontalContentAlignment}"
Margin="{x:Bind Padding}"
Content="{x:Bind HeaderContent}"/>
</Grid>
</Grid>
</UserControl>
Code-behind du contrle Jutilise un Messenger pour mabonner au changement
de DisplayMode du SplitView. SI le DisplayMode est
public sealed partial class PageHeader : UserControl
{
Overlay . Je mets une grosse marge (48px) pour que
public PageHeader() le bouton hamburger et le titre ne se chevauchent pas
{
this.InitializeComponent();
EasyMessenger.Default.Subscribe<bool>("SplitView-DisplayMode-Overlay", (isOverlay)=> {
if (isOverlay)
{
this.titleBar.Margin = new Thickness(overlayMargin, 0, 0, 0);
}
else
{
this.titleBar.Margin = new Thickness(defaultMargin, 0, 0, 0);
}
});
}
private const int defaultMargin = 12; Dependency Property
private const int overlayMargin = 48;
public UIElement HeaderContent permettant de personnaliser le
{ contenu du contrle selon
get { return (UIElement)GetValue(HeaderContentProperty); } chaque page
set { SetValue(HeaderContentProperty, value); }
}
public static readonly DependencyProperty HeaderContentProperty =
DependencyProperty.Register("HeaderContent", typeof(UIElement), typeof(PageHeader), new
PropertyMetadata(DependencyProperty.UnsetValue));
}
11
Voir lexemple XamlNavigation, qui nutilise pas tout fait la mme mthode, mais il ma
sembl observer quelques soucis
// navigation
mainFrame.Navigate(typeof(PageOne));
}
</Grid>
</Grid>
12
Marge de 12 en CompactInline
(panel ouvert et ferm)
3. Navigation model
Documentation
La navigation doit se faire dans deux sens. La barre de navigation doit tre synchronise
(navigation retour) avec les pages affiches.
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
var MenuItems = new ObservableCollection<MenuItem>();
MenuItems.Add(new MenuItem("HomePage", "Accueil", Symbol.Home));
MenuItems.Add(new MenuItem("VideosPage", "Vidos", Symbol.Video)) ;
MenuItems.Add(new MenuItem("MusicsPage", "Musiques", Symbol.Audio));
menusListView.ItemsSource = MenuItems;
if (menu.Id == "MusicsPage")
{
mainFrame.Navigate(typeof(MusicsPage));
}
}
Navigation Aller
Navigation Retour , aprs avoir cliqu sur le bouton retour de la barre de titre, le menu est
slectionn et synchronis par rapport la page affiche.
Il faut garder en tte ici que cest un scnario simple. On pourrait par exemple imaginer crer un
paramtre spcifique la navigation avec des proprits permettant de mieux grer celle-ci
(exemple la page doit elle tre prise en compte dans la navigation par la barre de menus?)
4. BackButton
Dans App pour rootFrame (ou dans le code de la page pour une Frame particulire)
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// etc.
Window.Current.Activate();
5. CommandBar, SymbolIcon,
FontIcon permet de dfinir un symbole qui nest pas inclus dans SymbolIcon (on peut saider avec la
table des caractres
<AppBarButton Label="FontIcon">
<AppBarButton.Icon>
<FontIcon FontFamily="Candara" Glyph="Σ"/>
</AppBarButton.Icon>
</AppBarButton>
PathIcon
<AppBarButton Label="PathIcon">
<AppBarButton.Icon>
<PathIcon Data="F1 M 16,12 20,2L 20,16 1,16"
HorizontalAlignment="Center"/>
</AppBarButton.Icon>
</AppBarButton>
BitmapIcon
<AppBarButton Label="BitmapIcon">
<AppBarButton.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/YouTube.png" />
</AppBarButton.Icon>
</AppBarButton>
Custom
<AppBarButton Label="Custom" HorizontalContentAlignment="Center">
<Grid Width="48" Height="48" Margin="0,-8,0,-4">
<SymbolIcon Symbol="Memo"/>
<TextBlock Text="2" Margin="0,2,0,0" Style="{StaticResource
CaptionTextBlockStyle}" HorizontalAlignment="Center"/>
</Grid>
</AppBarButton>
19
<Page.TopAppBar>
<CommandBar x:Name="topBar" ClosedDisplayMode="Compact">
<CommandBar.Content>
<StackPanel Orientation="Horizontal">
<AppBarButton Icon="Home" />
<!--etc.-->
</StackPanel>
</CommandBar.Content>
<Page.BottomAppBar>
<CommandBar>
<AppBarButton Icon="Accept" Label="Valider"/>
<!--etc.-->
</CommandBar>
</Page.BottomAppBar>
TopAppBar
BottomAppBar
Source
<MediaElement x:Name="mediaElement"
Source="/Assets/dhany.mp4"
AreTransportControlsEnabled="True" />
SetSource
<MediaElement x:Name="mediaElement" AreTransportControlsEnabled="True" />
Ouverture dune boite de dialogue
private async void button_Click(object sender, RoutedEventArgs e)
{
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".wmv");
picker.FileTypeFilter.Add(".mp4");
picker.FileTypeFilter.Add(".mp3");
picker.FileTypeFilter.Add(".wma");
picker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
Il est possible de customiser les contrles, en ajouter (un bouton like en plus par exemple)
7. Content Dialog
Menu Ajouter Nouvel lment Boite de dialogue de contenu
Exemple de ContentDialog
<ContentDialog
x:Class="UWPContentDialogDemo.MyContentDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWPContentDialogDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Ecrire une note" Titre et boutons de la
PrimaryButtonText="Envoyer" boite de dialogue
SecondaryButtonText="Annuler"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
SecondaryButtonClick="ContentDialog_SecondaryButtonClick"> Contenu
<StackPanel>
<TextBox Header="Titre"></TextBox>
<TextBox TextWrapping="Wrap" AcceptsReturn="True" Header="Contenu" Height="100"></TextBox>
</StackPanel>
</ContentDialog>
Afficher la boite de dialogue et grer le rsultat
private async void Button_Click(object sender, RoutedEventArgs e)
{
var dialog = new MyContentDialog();
var dialogResult = await dialog.ShowAsync();
if(dialogResult == ContentDialogResult.Primary)
{
}
else if (dialogResult == ContentDialogResult.Secondary)
{ }
}
22
<AutoSuggestBox x:Name="autoSuggestBox"
Margin="0,8,12,0"
Width="270"
PlaceholderText="Entrer le nom d'une ville Franaise"
QueryIcon="Find"
TextChanged="autoSuggestBox_TextChanged"
SuggestionChosen="autoSuggestBox_SuggestionChosen"
QuerySubmitted="autoSuggestBox_QuerySubmitted"
RelativePanel.AlignRightWithPanel="True" />
9. Popup
Exemple popup chargement affiche pendant le chargement des donnes
<Popup IsOpen="{Binding IsBusy}" VerticalAlignment="Center" HorizontalAlignment="Center">
<Grid Background="{ThemeResource ContentDialogBorderThemeBrush}" Height="100" Width="200">
<Grid.RenderTransform>
<TranslateTransform X="-100" Y="-50" /> Place correctement au centre de la page
</Grid.RenderTransform>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<ProgressRing VerticalAlignment="Center" IsActive="True"
Foreground="{ThemeResource ContentDialogDimmingThemeBrush}" />
<TextBlock x:Uid="loadingTextBlock" Foreground="{ThemeResource ContentDialogDimmingThemeBrush}"
Text="Loading" FontSize="22" FontWeight="Light" Margin="12,0,0,0" />
</StackPanel>
</Grid>
</Popup>
rootFrame.Content = splash;
Window.Current.Content = rootFrame;
}
Cration dune page avec image et progress ring.
<Grid Background="#D03133" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="180"/>
</Grid.RowDefinitions>
<Canvas Grid.RowSpan="2">
<Image x:Name="extendedSplashImage" Source="Assets/SplashScreen.png"/>
</Canvas>
<ProgressRing IsActive="True"
Grid.Row="1" Width="80" Height="80" Foreground="White" HorizontalAlignment="Center" />
</Grid>
24
splash = splashscreen;
if (splash != null)
{
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(OnDismissed);
splashImageRect = splash.ImageLocation;
PositionImage();
}
}
private void PositionImage()
{
extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.Left);
extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Top);
extendedSplashImage.Height = splashImageRect.Height / ScaleFactor;
extendedSplashImage.Width = splashImageRect.Width / ScaleFactor;
}
private void OnResize(Object sender, WindowSizeChangedEventArgs e)
{
if (splash != null)
{
splashImageRect = splash.ImageLocation;
PositionImage();
}
}
private async void OnDismissed(SplashScreen sender, object e)
{
// on peut effectuer un chargement, essayer de connecter lutilisateur, etc. par exemple
puis naviguer vers la page principale
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
WNavigationService.Default.Navigate(typeof(MainPage));
});
}
}
Chaque lment de base a une taille de
25
100x100. Ils sempilent horizontalement
(orientation) dans la limite de 4
11. VariableSizedWrapGrid
<VariableSizedWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="4" ItemHeight="100" ItemWidth="100">
<Rectangle Fill="Green" Width="200" Height="200" VariableSizedWrapGrid.RowSpan="2"
VariableSizedWrapGrid.ColumnSpan="2" Margin="4"/>
<Rectangle Fill="Gray" Width="200" VariableSizedWrapGrid.ColumnSpan="2" Margin="4"/>
<Rectangle Fill="Red" Margin="4"/>
<Rectangle Fill="Blue" Margin="4"/>
</VariableSizedWrapGrid>
On peut changer la largeur,
hauteur et ainsi dfinir
combien de colonnes, lignes
sont occupes
base.PrepareContainerForItemOverride(element, item);
}
Le modle
public class VariableItem
{
public string Title { get; set; }
public SolidColorBrush BackgroundColor { get; set; }
public int Height { get; set; }
public int Width { get; set; } Proprits lies pour dfinir llment
public int ColumnSpan { get; set; } dans le GridView, il pourrait avoir
public int RowSpan { get; set; }
// etc. dautres proprits avec des donnes
} rcupres
26
Ajout la page
<local:VariableGridView x:Name="variableGridView">
<local:VariableGridView.ItemTemplate>
<DataTemplate>
<Grid Background="{Binding BackgroundColor}"
Height="{Binding Height}" Width="{Binding Width}" Margin="4">
<TextBlock Text="{Binding Title}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</local:VariableGridView.ItemTemplate>
<local:VariableGridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Horizontal"
MaximumRowsOrColumns="4" ItemHeight="100" ItemWidth="100"/>
</ItemsPanelTemplate>
</local:VariableGridView.ItemsPanel>
</local:VariableGridView>
Dans le code-behind de la page
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
Items = new List<VariableItem>();
Items.Add(new VariableItem
{
Title = "First",
BackgroundColor = new SolidColorBrush(Colors.Green),
Height = 200,
Width = 200,
ColumnSpan = 2,
RowSpan = 2
});
Items.Add(new VariableItem
{
Title = "Second",
BackgroundColor = new SolidColorBrush(Colors.Gray),
Width = 200,
Height = 100,
ColumnSpan = 2
});
Items.Add(new VariableItem
{
Title = "Three",
BackgroundColor = new SolidColorBrush(Colors.Red),
Height = 100,
Width = 100,
});
Items.Add(new VariableItem
{
Title = "Four",
BackgroundColor = new SolidColorBrush(Colors.Blue),
Height = 100,
Width = 100,
});
variableGridView.ItemsSource = Items;
}
public List<VariableItem> Items { get; set; }
}
27
</Application>
Ou pour seulement des lments ou contrles avec lattribut RequestedTheme , exemple
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" RequestedTheme="Dark">
<!--etc-->
</RelativePanel>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="BackgroundBrush" Color="{ThemeResource SystemColorWindowColor}" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Application.Resources>
28
On peut galement dfinir les thmes dans des dictionnaires de ressources et les rendre accessibles
lapplication
<Application
x:Class="UWPThemesDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWPThemesDemo"
RequestedTheme="Dark">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Utilisation
<Grid Background="{ThemeResource BackgroundBrush}">
</Grid>
IV. DataTemplateSelector
Permet dafficher diffrents Templates dans une ListView ou un GridView pour une mme source de
donnes.
public class SearchResultTemplateSelector : DataTemplateSelector
{
public DataTemplate VideoTemplate { get; set; }
public DataTemplate ChannelTemplate { get; set; }
public DataTemplate PlayListTemplate { get; set; }
ViewModel
public class SearchPageViewModel : ViewModelBase
{
private ObservableCollection<ModelBase> _results;
public ObservableCollection<ModelBase> Results
{
get { return _results; }
set { SetProperty(ref _results, value); }
}
// etc.
}
Utilisation
ViewModel
public class MainPageViewModel
{
public ObservableCollection<ModelBase> Items { get; set; }
// Last
Items.Add(new LastItem("Afficher plus"));
}
}
On ajoute dans le code behind de la page une proprit pour le binding (avec x :Bind)
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
ViewModel = new MainPageViewModel();
}
public MainPageViewModel ViewModel { get; set; }
}
33
En ressources de la page
<local:LastTemplateSelector x:Key="LastTemplateSelector"
NormalTemplate="{StaticResource ImageOverlayTemplate}"
LastTemplate="{StaticResource LastTemplate}"/>
On dfinit un template simple pour le type LastItem
<DataTemplate x:Key="LastTemplate" x:DataType="models:LastItem">
<Grid Width="200" Height="200" Background="{ThemeResource SystemAccentColor}" Margin="4">
<TextBlock Text="{x:Bind Title}" Style="{StaticResource BaseTextBlockStyle}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
Le GridView avec ItemTemplateSelector et behavior
<GridView x:Name="itemsListView"
ItemsSource="{x:Bind ViewModel.Items}"
ItemTemplateSelector="{StaticResource LastTemplateSelector}"
SelectionMode="None"
IsItemClickEnabled="True">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="ItemClick">
<Core:InvokeCommandAction Command="{x:Bind ViewModel.GoDetailsPageCommand}"
CommandParameter="{x:Bind itemsListView.SelectedItem}"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</GridView>
34
Models
public sealed class DataSource
{
public static IEnumerable<DataGroup> GetGroups()
{
var groups = new List<DataGroup>();
groupA.Items.Add(new DataItem("Aanor"));
groupA.Items.Add(new DataItem("Aaricia"));
groupA.Items.Add(new DataItem("Aaron"));
// etc.
groups.Add(groupA);
// etc.
return groups;
}
}
public class DataGroup
{
public string TitleGroup { get; private set; }
public ObservableCollection<DataItem> Items { get; set; }
ViewModel
public class MyDataViewModel
{
public ObservableCollection<DataGroup> Groups { get; set; }
DataTemplates
Pour ListView
Texte seul
<DataTemplate x:Key="TextListTemplate" x:DataType="models:DataItem">
<Grid Width="280">
<TextBlock Text="{x:Bind Title}" Style="{StaticResource BaseTextBlockStyle}"
Margin="8,0,0,0" HorizontalAlignment="Left" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
Icone et texte
<DataTemplate x:Key="IconTextTemplate" x:DataType="models:DataItem">
<StackPanel Orientation="Horizontal" Width="500">
<Image Height="45" Width="45" Margin="0,8,0,8" Source="{x:Bind Image}" Stretch="UniformToFill"/>
<StackPanel Orientation="Vertical" VerticalAlignment="Top" Margin="8,8,0,0">
<TextBlock Text="{x:Bind Title}" Style="{StaticResource BaseTextBlockStyle}" />
<TextBlock Text="{x:Bind Subtitle}" Margin="0,4,8,0"
Style="{StaticResource BodyTextBlockStyle}" />
</StackPanel>
</StackPanel>
</DataTemplate>
37
Image et texte
<DataTemplate x:Key="ImageTextListTemplate" x:DataType="models:DataItem">
<StackPanel Orientation="Horizontal" Width="500" Height="130">
<Image Height="110" Width="110" Margin="0,8,0,8" Source="{x:Bind Image}" Stretch="UniformToFill"/>
<StackPanel VerticalAlignment="Center" Width="380" Margin="8,8,0,0">
<TextBlock Text="{x:Bind Title}" Style="{StaticResource BaseTextBlockStyle}" />
<TextBlock Text="{x:Bind Subtitle}" TextWrapping="WrapWholeWords"
Style="{StaticResource CaptionTextBlockStyle}" />
<TextBlock Text="{x:Bind Description}" TextWrapping="WrapWholeWords" Margin="0,8,0,0"
Style="{StaticResource BodyTextBlockStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
Overlay
<DataTemplate x:Key="ImageOverlayTemplate" x:DataType="models:DataItem">
<Grid Height="110">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Source="{x:Bind Image}" Stretch="Uniform" Grid.Column="1" Grid.RowSpan="2"
Margin="0,8,0,8"/>
<Border Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" Margin="0,8,0,8">
<TextBlock Text="{x:Bind Title}" Margin="8,8,0,0" TextWrapping="Wrap"
HorizontalAlignment="Left" Style="{StaticResource BaseTextBlockStyle}"/>
</Border>
<TextBlock Text="{x:Bind Subtitle}" Grid.Row="1" Style="{StaticResource BodyTextBlockStyle}"
TextWrapping="Wrap" Margin="8,0,0,0"/>
</Grid>
</DataTemplate>
</Page.Resources>
38
Pour GridView
Texte seul
<DataTemplate x:Key="TextTemplate" x:DataType="models:DataItem">
<StackPanel Orientation="Horizontal" Width="300">
<TextBlock Text="{x:Bind Title}" Style="{StaticResource BaseTextBlockStyle}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>
Icone et texte
<DataTemplate x:Key="IconTextTemplate" x:DataType="models:DataItem">
<StackPanel Orientation="Horizontal" Width="280">
<Image Source="{x:Bind Image}" Width="45" Height="45" Margin="8" Stretch="UniformToFill"/>
<StackPanel VerticalAlignment="Center" Margin="8,0">
<TextBlock Text="{x:Bind Title}" Style="{StaticResource BaseTextBlockStyle}" />
<TextBlock Text="{x:Bind Subtitle}" />
</StackPanel>
</StackPanel>
</DataTemplate>
Image et texte
<DataTemplate x:Key="ImageTextTemplate" x:DataType="models:DataItem">
<StackPanel Orientation="Horizontal" Width="500" Height="130">
<Image Source="{x:Bind Image}" Stretch="Fill" Height="110" Width="110" Margin="8,8,0,8"/>
<StackPanel Width="350" Margin="8,8,0,0" VerticalAlignment="Center">
<TextBlock Text="{x:Bind Title}" Style="{StaticResource BaseTextBlockStyle}" />
<TextBlock Text="{x:Bind Subtitle}" Style="{StaticResource CaptionTextBlockStyle}"/>
<TextBlock Text="{x:Bind Description}" TextWrapping="Wrap" Margin="0,8,0,0"/>
</StackPanel>
</StackPanel>
</DataTemplate>
39
Overlay
<DataTemplate x:Key="ImageOverlayTemplate" x:DataType="models:DataItem">
<StackPanel Height="130" Width="190" Margin="4,4,4,8">
<TextBlock Text="{x:Bind Title}" Margin="8,4" Width="186"
Style="{StaticResource BaseTextBlockStyle}" HorizontalAlignment="Left"/>
<Image Source="{x:Bind Image}" Margin="8,0,8,8" Stretch="UniformToFill"/>
</StackPanel>
</DataTemplate>
40
VI. Adaptive UI
Une application UWP doit pouvoir sexcuter sur diffrents appareils. Il va falloir adapter la page
pour les diffrentes rsolutions et orientations (Portrait, paysage).
6R
Reposition
Resize
Reflow (basculer de 2 3 colonnes par exemple)
Reveal
Replace
Re-architect
Utilisation Visual States et AdaptiveTrigger pour dplacer des blocs ou lments, redimensionner,
cacher, etc.
Snap points :
- 320
- 548 Phone
- 720 Tablet
- 1024 Desktop
1. Adaptive Triggers
3. Changer les proprits des lments selon les tats AdaptiveTrigger ou Custom Trigger
Slectionner ltat dans le panneau Etats et llment dans le panneau Objets et chronologie ,
puis modifier les proprits de cet lment dans le panneau Proprits
42
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="VisualStateMin548">
<VisualState.Setters>
<Setter Target="textBlock.(RelativePanel.RightOf)" Value="image"/>
</VisualState.Setters>
> 548 <VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="548"/>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
2. Master details
> 548
De 0 548
La liste occupe toute la largeur de la page (ColumnSpan=2), la partie dtail est cache (Collapsed) et
lorsque lon clique sur un lment de la liste on navigue vers une page dtails
Une variante consiste donner un nom chaque colonne de la grille (exemple masterColumn
et detailsColumn ) et changer la taille pour de 0 548 (ou 720) passer masterColumn * et
detailsColumn 0. Exemple XamlMasterDetail
44
<Page >
<Page.Transitions> On peut ajouter une transition
<TransitionCollection>
<NavigationThemeTransition /> page pour effet de retour
</TransitionCollection>
</Page.Transitions>
<VisualState x:Name="VisualStateMin548">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="548"/>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
On change ensuite les proprits des lments de la page selon les tats visuels.
47
Dans cet exemple, on affiche une image quand on est sur desktop, et une autre quand on est sur
mobile
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DeviceFamilyStates">
<VisualState x:Name="Desktop">
<VisualState.StateTriggers>
<triggers:DeviceFamilyTrigger DeviceFamily="Windows.Desktop" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="desktopImage.Visibility" Value="Visible" />
<Setter Target="mobileImage.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Mobile">
<VisualState.StateTriggers>
<triggers:DeviceFamilyTrigger DeviceFamily="Windows.Desktop" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="desktopImage.Visibility" Value="Collapsed" />
<Setter Target="mobileImage.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
4. DeviceFamily
On peut crer une version de page selon les devices
Vue correspondante
pour Mobile
Si on navigue vers la page Scenario4 , automatiquement la vue pour Mobile sera affiche si on est
sur ce device.
Les +
- Meilleures performances que le binding classique . Trs performant pour afficher des
listes.
- Va chercher automatiquement les proprits dans le code-behind de la page sans dfinir de
DataContext. Pour lutilisation de ViewModels on dfinit donc directement une proprit
dans le code-behind.
- Le mode par dfaut de binding est OneTime . Il faut donc dfinir un mode OneWay ou
TwoWay si ce nest pas suffisant.
- On peut utiliser x :Bind pour binder des vnements, permet dviter lutilisation de
RelayCommand ou de behavior pour des scnarios simples.
Les -
- Problme avec les commandes dans les DataTemplates de fichier de ressources (Besoin
daller chercher le DataContext du parent)
- Problme avec SelectedItem (renvoyant un objet) avec ListView / GridView .., besoin de faire
des convertisseurs ?
- Problme avec les styles
- Les attributs ElementName, RelativeSource, Source, UpdateSourceTrigger ne sont pas pris
en charge par x :Bind
- Solution : il faudra parfois mlanger le binding classique et binding avec x :Bind . On rgle
alors le DataContext sur le mme ViewModel dfini en proprit dans le code-behind de la
page.
1. Binding de collection
On dfinit une proprit dans le code-behind de la page sans dfinir de DataContext
public sealed partial class Scenario1 : Page
{
public Scenario1()
{
this.InitializeComponent();
People = new ObservableCollection<Person>
{
new Person { Name ="Marie Bellin"},
new Person { Name ="Jrme Romagny"}
};
}
public ObservableCollection<Person> People { get; set; }
}
(Le modle utilis)
public class Person
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
50
Si aucun DataTemplate nest dfini cest la mthode
2. Binding dans la page ToString des lments qui est appele
Exemple
public class MyViewModel
{ Les 3 signatures
public void DoWork1()
{ acceptes
}
public void DoWork2(object sender, RoutedEventArgs e)
{
}
public void DoWork3(object sender, object e)
{
}
}
Dans le code-behind de la page
public sealed partial class Scenario4 : Page
{
public Scenario4()
{
this.InitializeComponent();
ViewModel = new MyViewModel();
}
public MyViewModel ViewModel { get; set; }
}
Dans le code-behind
private void Button_Click(object sender, RoutedEventArgs e)
{
FindName("myGrid");
}
Il faut donner lillusion que lapplication na pas t suspendue quand celle-ci est rsume.
deferral.Complete();
}
Restaurer la navigation
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// etc.
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
if (ApplicationData.Current.LocalSettings.Values.ContainsKey("NavigationState"))
{
rootFrame.SetNavigationState((string)ApplicationData.Current.LocalSettings.Values["NavigationState"]);
}
}
}
2. Etats de la page et donnes
Sauver les tats de la page courante la suspension ( code-behind de la page )
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
vm.SaveData();
}
ViewModel
public void LoadData()
{
if (ApplicationData.Current.RoamingSettings.Values.ContainsKey("ValueOne"))
{
ValueOne = ApplicationData.Current.RoamingSettings.Values["ValueOne"].ToString();
}
if (ApplicationData.Current.RoamingSettings.Values.ContainsKey("ValueTwo"))
{
ValueTwo = ApplicationData.Current.RoamingSettings.Values["ValueTwo"].ToString();
}
}
public void ClearData()
{
if (ApplicationData.Current.RoamingSettings.Values.ContainsKey("ValueOne"))
{
ApplicationData.Current.RoamingSettings.Values.Remove("ValueOne");
}
if (ApplicationData.Current.RoamingSettings.Values.ContainsKey("ValueTwo"))
{
ApplicationData.Current.RoamingSettings.Values.Remove("ValueTwo");
}
}
56
Tile
On dfinit les Assets toujours dans le manifeste de lapplication, onglet Ressources visuelles
310x310
57
Note : si on dfinit la couleur darrire-plan des vignettes sur transparent , cest alors la couleur
daccent de Windows qui est appliqu
Vignette secondaire : ajoute par code. La vignette est dsormais ajoute directement sans boite de
dialogue (comme ctait le cas avec Windows 8.1)
// dtails
tile.VisualElements.ShowNameOnSquare150x150Logo = true;
tile.VisualElements.ShowNameOnWide310x150Logo = true;
tile.VisualElements.ShowNameOnSquare310x310Logo = true;
//tile.VisualElements.BackgroundColor = Colors.DarkOrange;
tile.VisualElements.ForegroundText = ForegroundText.Light;
tile.RoamingEnabled = false;
Documentation
59
Adaptive Tiles
On peut toujours utiliser les templates de Windows 8.1 ou on peut utiliser les Adaptive Templates
qui permettent plus de souplesse et de personnalisation
Exemple
Image en arrire-plan,
texte par-dessus avec styles Image inline
branding :
nom et logo
(44x44)
}
60
Toast
Les toasts servent soit afficher un message, soit propose une action.
On peut utiliser les templates de toast de Windows 8.1 ou on peut utiliser les adaptives templates.
private void OnSendToast(object sender, RoutedEventArgs e)
{
string title = "Mon application";
string message = "Nouveau message!";
string xml = string.Format(@"<toast>
<visual>
<binding template=""ToastText02"">
<text id=""1"">{0}</text>
<text id=""2"">{1}</text>
</binding>
</visual>
</toast>", title, message);
var document = new XmlDocument();
document.LoadXml(xml);
var notification = new ToastNotification(document);
ToastNotificationManager.CreateToastNotifier().Show(notification);
}
Toast
Centre de
Adaptive toast notifications
Reminder, alarm ou
Scnarios
incomingCall
<toast scenario=""reminder"">
Historique de notification
ToastNotificationManager.History.Clear();
Il est possible de dfinir les applications pouvant envoyer des notifications dans les options de
Windows 10 ( Systme Notifications et actions ou depuis le centre de notifications de la
barre de tches)