En Windows 10 UWP, on se retrouve généralement à gérer le Back (retour en arrière) dans nos applications. Ce qui selon nos besoins peut nous amener à des cas complexes de navigation.
Par exemple, un type de page master/details où la page details va ouvrir un popup puis le fermer quand l’action sera finie. Il sera donc compliqué de faire une gestion propre de notre navigation car on se retrouvera dans plusieurs de nos pages, à gérer les différents back, mobile et pc, et donc, avoir plusieurs fois ce type d’élément :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if (ApiInformation.IsTypePresent(DevicesTool.PHONE_INPUT_HARDWAREBUTTONS)) HardwareButtons.BackPressed += HardwareButtons_BackPressed; else SystemNavigationManager.GetForCurrentView().BackRequested += BackRequestedTool_BackRequested; private static async void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) { ... } private static async void BackRequestedTool_BackRequested(object sender, BackRequestedEventArgs e) { ... } |
Néanmoins il faut faire attention en utilisant les événements Back. En effet, si vous avez plusieurs évènements de ce type attaché à vos pages, tous les événements seront levés en même temps quand l’utilisateur fera un back. Il vous faudra donc vous désabonner des événements qui ne seront pas nécessaires, mais cela peut être fastidieux et pas vraiment très propre quand votre application comporte un certain nombre de pages.
A la place, je vous propose une petite classe gérant tous les back (PC, mobile, et souris) qui pourrait simplifier votre vie de développeur :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
public static class BackRequestedTool { #region [ Fields ] private static List<Func<bool, Task<bool>>> listCommands; #endregion [ Fields ] #region [ Properties ] public static event Func<bool, Task<bool>> BackCommand { add => RegisterCommand(value); remove => UnregisterCommand(value); } #endregion [ Properties ] #region [ Events ] private static async void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) { e.Handled = await ExecuteCommand(e.Handled); } private static async void BackRequestedTool_BackRequested(object sender, BackRequestedEventArgs e) { e.Handled = await ExecuteCommand(e.Handled); } private static async void CoreWindow_PointerReleased(CoreWindow sender, PointerEventArgs args) { //Click back mouse if (args?.CurrentPoint?.Properties?.PointerUpdateKind == PointerUpdateKind.XButton1Released) args.Handled = !await ExecuteCommand(!args.Handled); } #endregion [ Events ] #region [ Methods ] /// <summary> /// Subscribe to the back event. /// </summary> public static void Initialize() { listCommands = new List<Func<bool, Task<bool>>>(); if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) HardwareButtons.BackPressed += HardwareButtons_BackPressed; else SystemNavigationManager.GetForCurrentView().BackRequested += BackRequestedTool_BackRequested; Window.Current.CoreWindow.PointerReleased += CoreWindow_PointerReleased; } /// <summary> /// Dispose back event /// </summary> public static void Dispose() { listCommands?.Clear(); listCommands = null; SystemNavigationManager.GetForCurrentView().BackRequested -= BackRequestedTool_BackRequested; if (ApiInformation.IsTypePresent(DevicesTool.PHONE_INPUT_HARDWAREBUTTONS)) HardwareButtons.BackPressed -= HardwareButtons_BackPressed; Window.Current.CoreWindow.PointerReleased -= CoreWindow_PointerReleased; } #endregion [ Methods ] #region [ Functions ] /// <summary> /// Register a command to be execute when back is invoke. /// </summary> /// <param name="command">The command to execute</param> private static void RegisterCommand(Func<bool, Task<bool>> command) { if (command != null) listCommands?.Add(command); } /// <summary> /// Unregister the specified <see cref="Action"/> from the stack. /// </summary> /// <param name="command">The command to unregister</param> private static void UnregisterCommand(Func<bool, Task<bool>> command) { if (command != null) listCommands?.Remove(command); } /// <summary> /// Execute the command. /// </summary> private static async Task<bool> ExecuteCommand(bool handled) { if (listCommands?.Count > 0) return await listCommands?.Last()?.Invoke(handled); else return false; } #endregion [ Functions ] } |
Attention pour le mobile, pensez bien à rajouter la dll dans vos références.
Cette classe a pour but de gérer une « pile » d’action, qui lancera la dernière action qui a été attachée dans vos différentes pages.
Pour cela, il vous suffit d’initialiser la classe une seule fois :
1 |
BackRequestedTool.Initialize(); |
puis dans les différentes pages où vous souhaitez gérer votre back, faire :
1 2 3 4 5 6 7 8 9 |
BackRequestedTool.BackCommand += this.BackRequestedTool_BackCommand; private Task<bool> BackRequestedTool_BackCommand(bool arg) { ...action arg = false; return Task.FromResult<bool>(arg); } |
Vous pourrez ainsi gérer le back indépendamment des autres pages sans vous souciez de la gestion des événements et d’avoir un seul et unique événement back lancé.