In Power Apps non esiste un controllo menu, ma è comunque possibile realizzarlo usando i controlli di tipo Gallery.
Controllo galleryControllo gallery
In questo esempio realizzerò un mega menu a 3 livelli:
Mega menu apertoMega menu aperto
Mega menu chiusoMega menu chiuso

Sorgente dati


Come sorgente dati per il menu, uso una lista di SharePoint Online, la struttura dei dati è, per semplicità, una lista piatta con i seguenti campi:
  • ID: campo standard di SharePoint, identificativo univoco (numerico)
  • Level1ID: identificativo univoco del primo livello di menu (stringa)
  • Level1Desc: titolo della voce di menu di primo livello (stringa)
  • Level1Sort: valore numerico per determinare l'ordinamento delle voci di menu di primo livello (numerico)
  • Level2ID: identificativo univoco del secondo livello di menu (stringa)
  • Level2Desc: titolo della voce di menu di secondo livello (stringa)
  • Level2Sort: valore numerico per determinare l'ordinamento delle voci di menu di secondo livello (numerico)
  • Level3ID: identificativo univoco del terzo livello di menu (stringa)
  • Level3Desc: titolo della voce di menu di terzo livello (stringa)
  • Level3Sort: valore numerico per determinare l'ordinamento delle voci di menu di terzo livello (numerico)
Tabella dati menuTabella dati menu
La stessa cosa si può realizzare con qualsiasi sorgente dati, come ad esempio su una tabella SQL sia online che on-premises tramite il gateway.

Power Apps


Partendo da una Power Apps vuota, va prima di tutto creata la connessione ai dati, ovvero la connessione alla lista SharePoint
Data sourcesData sources
poi va realizzata questa struttura di controlli:
Struttura dei controlliStruttura dei controlli
dove i controlli principali sono:
  • glryMenu1_1 gallery per il menu di primo livello
  • glryMenu2_1 gallery per il menu di secondo livello
  • glryMenu3_1 gallery per il menu di tezo livello
Controlli evidenziatiControlli evidenziati
Le gallery di primo e terzo livello contengono dei button in quanto devono essere cliccabili. Mentre la gallery di secondo livello contiene una label per la voce di secondo livello e, ovviamente, la gallery di terzo livello.
Per questo caso ho deciso che è selezionabile solo la voce di terzo livello
Collection per i menù

La proprietà items delle gallery deve essere impostata in questo modo
glryMenu1_1.Items = SortByColumns(GroupBy(TestPowerAppsMenu, "Level1ID", "Level1Desc", "Level1Sort", "GroupMenu1"), "Level1Sort");

glryMenu2_1.Items = SortByColumns(GroupBy(Filter(TestPowerAppsMenu, Level1ID = glryMenu1_1.Selected.Level1ID), "Level2ID", "Level2Desc", "Level2Sort", "GroupMenu2"), "Level2Sort");

glryMenu3_1.Items = SortByColumns(Filter(TestPowerAppsMenu, Level1ID = glryMenu1_1.Selected.Level1ID, Level2ID = ThisItem.Level2ID), "Level3Sort");
in questo modo, per ogni livello di menu, se necessario, estraggo i dati (Filter), li raggruppo (GroupBy) e li ordino (SortByColumns).

A questo punto il menù è predisposto per visualizzare i dati, va impostato cosa visualizzare tramite la proprietà Text
btnMenu1Item1.Text = ThisItem.Level1Desc;

lblMenu2Item1.Text = ThisItem.Level2Desc;

btnMenu3Item1.Text = ThisItem.Level3Desc;
ThisItem è un oggetto che si riferisce al record corrente visualizzato dal controllo Gallery
Tutti i metodi OnSelect dei controlli dentro le gallery, devono essere impostati a Select(Parent)
Apertura / Chiusura menù

Il passo successivo è gestire l'apertura e la chiusura del menu.
Per questo servono delle variabili da inizializzare sull'evento App.OnStart
App.OnStart = Set(MenuIDSelected, 0);Set(MenuLevel1IDSelected, "");Set(MenuIDOpen, "");
e Screen.Onvisible
scrnMenu.OnVisible = Set(MenuIDOpen, "");
L'espressione del metodo OnVisible, viene invocato ogni volta che si visualizza uno Screen e va impostata su tutti quelli in cui dovrà essere copiato il menù.
L'espressione OnStart viene invocata solo una volta all'avvio dell'applicazione.
Le variabili sono:
  • MenuIDSelected: conterrà l'ID univoco della tabella quando si seleziona una voce di terzo livello
  • MenuLevel1IDSelected: conterrà il Level1ID del menù di primo livello, relativo alla voce di terzo livello selezionata
  • MenuIDOpen:conterrà la voce di menù attualmente attiva (Level1ID) e verrà usato per gestire l'apertura del menù

Adesso serve associare la variabile MenuIDOpen alla proprietà Visible del gruppo grpMenuLevel2
grpMenuLevel2.Visible = MenuIDOpen <> "";
Successivamente va gestita l'apertura del menu, tramite il settaggio della variabile
glryMenu1_1.OnSelect = Set(MenuIDOpen, If(ThisItem.Level1ID = MenuIDOpen, "", ThisItem.Level1ID));
Questa espressione fa in modo che il menu si apra (visualizzato) cliccando su una voce che non è quella attualmente selezionata e si chiuda (nascosto) se clicco sulla stessa voce (del menu di primo livello).
L'evento OnSelect viene sollevato al click sull'elemento.

Devo anche gestire la chiusura quando clicco fuori dal menù, ad esempio quando clicco sul logo (imgLogo_1) oppure al di fuori del menù (rectMenuChiusura2_1 con sfondo trasparente). Questo lo si fa tramite il metodo OnSelect:
imgLogo_1.OnSelect = Set(MenuIDOpen, "");
rectMenuChiusura2_1.OnSelect = Set(MenuIDOpen, "");
Perchè funzioni la chiusura sul click, bisogna assicurarsi che, come ordine di visualizzazione, l'elemento rectMenuChiusura2_1 sia sopra gli altri controlli quando il menù è aperto.
Per cambiare l'ordinamento dei controlli usa il menù Reorder
Ordinamento dei controlliOrdinamento dei controlli

Selezione del menu


L'ultimo passo, è fare in modo che il click sulla voce di terzo livello, provochi la chiusura del menu e salvi i valori del record corrente nelle variabili
glryMenu3_1.OnSelect = Set(MenuIDSelected, ThisItem.ID); Set(MenuLevel1IDSelected, ThisItem.Level1ID); Set(MenuIDOpen, "");
variabili che poi visualizzo nelle label di debug:
lblDebugLevel1.Text = "Level1ID: " & MenuLevel1IDSelected;
lblDebugLevel3.Text = "ID menu: " & MenuIDSelected;
Un ultima finezza, evidenzio il menù di primo livello corrente tramite sottolineatura:
btnMenu1Item1.Underline = If(MenuIDOpen = "",  MenuLevel1IDSelected = ThisItem.Level1ID, MenuIDOpen = ThisItem.Level1ID)
questo sia per evidenziare che è il corrente selezionato quando il menù e chiuso, sia per evidenziare quello attivo quando è aperto.

Vedi anche Gallery control in canvas apps