Ordinamento manuale di una gallery Power Apps
Può capitare di dover gestire in Power Apps un ordinamento manuale in una lista, ad esempio, in una Todo list, si può voler definire una diversa priorità degli elementi da gestire tramite appositi pulsanti di spostamento su e giù.Per far questo è necessario avere una lista SharePoint o tabella SQL con un campo numerico intero, ad esempio di nome Position.La Gallery dovrà avere 2 pulsanti up e downcon ad esempio questa formula come query sui dati:
Lo spostamento andrà realizzato tramite il metodo RowNumber associando il seguente codice di spostamento nell'evento OnSelect dei pulsanti:
Visto che la colonna Position potrebbe contenere dei valori non consecutivi o duplicati a causa di interventi manuali sulla lista, come prima cosa creo una collection temporanea _TableRowNumber ordinata per Position con l'aggiunta di una colonna RowNumber contentente un numero pregressivo che parte da 1.
A questo punto, partendo dalla riga corrente, è sufficiente scambiare i RowNumber con la riga precedente (move up) o successiva (move down), in base al pulsante premuto.
In ultimo salvo i valori di RowNumber sulla campo Position della lista/tabella.
A questo punto il pulsante up conterrà:
quello down
infine Gallery.OnSelect conterrà una If che gestirà gli eventi move (up/down) oppure (else) gli altri eventi della riga
Il codice completo della Gallery.OnSelect sarà
Per far questo si può gestire la proprietà DisplayMode confrontando gli ID della prima e ultima riga nella Gallery.
Il pulsante up userà l'istruzione FirstN:
mentre quello down userà LastN:
anche in questo caso devo va usata la stessa formula della proprietà Gallery.Items (SortByColumns(TodoList, "Position", Ascending)).
Power Apps
Gallery.Items= SortByColumns(TodoList, "Position", Ascending)
E' fondamentale che l'ordinamento sia fatto sul campo Position.
Lo spostamento andrà realizzato tramite il metodo RowNumber associando il seguente codice di spostamento nell'evento OnSelect dei pulsanti:
Power Apps
UpdateContext(
{
_MoveUp: "up", /* impostare "down" per scendere */
_FirstRowNumber: 0,
_FirstID: ThisItem.ID
}
);
/* salvo la query di ordinamento basata sul campo Position, deve coincidere con quella impostata nella Gallery.Items */
ClearCollect(
_TmpTable,
SortByColumns(
TodoList,
"Position",
Ascending
)
);
/* creo una nuova lista ordinata con RowNumber sequenziale/progressivo e l'ID riga */
Clear(_TableRowNumber);
ForAll(
_TmpTable,
Collect(
_TableRowNumber,
Last(
FirstN(
AddColumns(
ShowColumns(
_TmpTable,
"ID",
"Position"
),
"RowNumber",
CountRows(_TableRowNumber) + 1
),
CountRows(_TableRowNumber) + 1
)
)
)
);
/* faccio pulizia di quello che non serve più */
Clear(_TmpTable);
/* trovo la riga corrente */
UpdateContext(
{
_FirstRowNumber: LookUp(
_TableRowNumber,
ID = _FirstID
).RowNumber
}
);
/* e quella successiva o precedente */
UpdateContext(
{
_SecondRow: LookUp(
_TableRowNumber,
RowNumber = _FirstRowNumber + If(
_MoveUp = "up",
-1,
1
)
)
}
);
/* procedo con lo scambio ed aggiorno il db/lista */
If(
IsBlank(_SecondRow) = false,
/* scambio */
Patch(
_TableRowNumber,
LookUp(
_TableRowNumber,
ID = _FirstID
),
{RowNumber: _SecondRow.RowNumber}
);
Patch(
_TableRowNumber,
LookUp(
_TableRowNumber,
ID = _SecondRow.ID
),
{RowNumber: _FirstRowNumber}
);
/* aggiorno i valori sul DB */
ForAll(
_TableRowNumber,
If(
_TableRowNumber[@Position] <> _TableRowNumber[@RowNumber],
/* aggiorno solo se sono cambiati rispetto all'esistente */
Patch(
TodoList,
LookUp(
TodoList,
ID = _TableRowNumber[@ID]
),
{Position: _TableRowNumber[@RowNumber]}
)
);
);
);
/* faccio pulizia di quello che non serve più */
Clear(_TableRowNumber);
UpdateContext(
{
_MoveUp: "",
_SecondRow: Blank()
}
);
A questo punto, partendo dalla riga corrente, è sufficiente scambiare i RowNumber con la riga precedente (move up) o successiva (move down), in base al pulsante premuto.
In ultimo salvo i valori di RowNumber sulla campo Position della lista/tabella.
Attenzione il sistema proposto funziona bene su liste con poche decine elementi, pena un calo delle prestazioni.
Nel caso del pulsante di spostamento in giù (down), copiare il codice e cambiare l'impostazione delle variabile _MoveUpPower Apps
UpdateContext(
{
_MoveUp: "down",
_FirstRowNumber: 0,
_FirstID: ThisItem.ID
}
);
...
Metodo alternativo
Anziché duplicare lo stesso codice nei due pulsanti up e down, si può mettere il codice in un unico punto sull'evento Gallery.OnSelect e nei pulsanti up e down impostare solo una variabile.A questo punto il pulsante up conterrà:
Power Apps
gallerySxIcnUp.OnSelect =
UpdateContext({_MoveUp: "up"});
Select(Parent); /* richiamo l'evento Gallery.OnSelect */
Power Apps
gallerySxIcnDown.OnSelect =
UpdateContext({_MoveUp: "down"});
Select(Parent)
Power Apps
Gallery.OnSelect =
If(_MoveUp ="up" Or _MoveUp = "down",
/* move */
...,
/* else */
...
);
Power Apps
If(
_MoveUp = "up" Or _MoveUp = "down",
/* move */
UpdateContext({_FirstID: ThisItem.ID});
/* salvo la query di ordinamento basata sul campo Position */
ClearCollect(
_TmpTable,
SortByColumns(
TodoList,
"Position",
Ascending
)
);
/* creo una nuova lista ordinata con RowNumber sequenziale/progressivo e l'ID riga */
Clear(_TableRowNumber);
ForAll(
_TmpTable,
Collect(
_TableRowNumber,
Last(
FirstN(
AddColumns(
ShowColumns(
_TmpTable,
"ID",
"Position"
),
"RowNumber",
CountRows(_TableRowNumber) + 1
),
CountRows(_TableRowNumber) + 1
)
)
)
);
/* faccio pulizia di quello che non serve più */
Clear(_TmpTable);
/* trovo la riga corrente */
UpdateContext(
{
_FirstRowNumber: LookUp(
_TableRowNumber,
ID = _FirstID
).RowNumber
}
);
UpdateContext(
{
_SecondRow: LookUp(
_TableRowNumber,
RowNumber = _FirstRowNumber + If(
_MoveUp = "up",
-1,
1
)
)
}
);
/* procedo con lo scambio ed aggiorno il db/lista */
If(
IsBlank(_SecondRow) = false,
/* scambio */
Patch(
_TableRowNumber,
LookUp(
_TableRowNumber,
ID = _FirstID
),
{RowNumber: _SecondRow.RowNumber}
);
Patch(
_TableRowNumber,
LookUp(
_TableRowNumber,
ID = _SecondRow.ID
),
{RowNumber: _FirstRowNumber}
);
/* aggiorno i valori sul DB */
ForAll(
_TableRowNumber,
If(
_TableRowNumber[@Position] <> _TableRowNumber[@RowNumber],
/* aggiorno solo se sono cambiati rispetto all'esistente */
Patch(
TodoList,
LookUp(
TodoList,
ID = _TableRowNumber[@ID]
),
{Position: _TableRowNumber[@RowNumber]}
)
);
);
);
/* faccio pulizia di quello che non serve più */
Clear(_TableRowNumber);
UpdateContext({_SecondRow: Blank()});
,
/* else*/
...
);
/* resetto la variabile con l'evento */
UpdateContext({_MoveUp: ""});
Attenzione è importante alla fine resettare la variabile _MoveUp.
Gestione abilitazione pulsanti
Idealmente il pulsante up sulla prima riga dovrebbe essere disabilitato così come il pulsante down nell'ultima riga.Per far questo si può gestire la proprietà DisplayMode confrontando gli ID della prima e ultima riga nella Gallery.
Il pulsante up userà l'istruzione FirstN:
Power Apps
gallerySxIcnUp.DisplayMode = If(First(FirstN(SortByColumns(TodoList, "Position", Ascending),1)).ID = ThisItem.ID, DisplayMode.Disabled, DisplayMode.Edit)
Power Apps
gallerySxIcnDown.DisplayMode = If(First(LastN(SortByColumns(TodoList, "Position", Ascending),1)).ID = ThisItem.ID, DisplayMode.Disabled, DisplayMode.Edit)