Il LongListSelector è un controllo chiave dell'UI di Windows Phone, per la sua peculiarità di suddividere in gruppi la lista degli elementi visualizzati, ognuno dei quali è indentificato da un'header che rappresenta il raggruppamento.
Questo controllo viene utilizzato nella lista dei contatti che sono raggruppati alfabeticamente; effettuando il tap sull'header, viene mostrata la sola lista dei gruppi (jump-list), così da "saltare" tra un gruppo e l'altro.
Benché questo controllo ricalchi nel funzionamento di quello nativo in Windows Phone, manca di alcune caratteristiche per renderlo fedele al look and feel di Metro e del device reale.
Infatti, il controllo, contrariamente alla controparte nativa, non prevede nessun tipo di animazione all'apertura della jump-list. E' possibile aggirare questo limite creando un controllo custom partendo da quello presente nel toolkit, oppure con un behavior, come nel caso descritto in questo script.
Come prima cosa creiamo una classe che estenda il tipo Behavior
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.GroupViewOpened += GroupOpened;
AssociatedObject.GroupViewClosing += GroupClosing;
}Il primo GroupViewOpened viene sollevato quando la jump-list è completamente aperta, mentre GroupViewClosing viene sollevato prima della sua chiusura.
Questa difformità del timing degli eventi ci costringe a creare un workaround per applicare la trasformazioni inziale agli elementi della jump-list prima che siano visualizzati e evitare così fastidiosi sfarfallii.
Il workaround consiste del creare una AttachedProperty da utilizzare per "marcare" il controllo al quale sarà applicata l'animazione.
<DataTemplate x:Key="GroupDataTemplate" >
<Grid JumpListAnimationBehavior:AddGroupAnimationBehavior.IsItemGroup="true"
Height="90"
Width="90"
Background="#FF3D9FB6"
Margin="0,0,12,12">
<TextBlock Text="{Binding Title}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>Nel nostro esempio, la proprietà IsItemGroup viene utilizzata per applicare la trasformazione iniziale agli elementi della jump-list prima che siano visualizzati.
private static void CallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Grid)d).Projection = new PlaneProjection { RotationX = -90 };
}Nel codice precedente, nel callback della attached property creiamo e assegniamo all'elemento una nuova PlaneProjection ruotando l'elemento di -90 gradi sull'asse X.
Spostiamoci nel gestore dell'evento GroupViewOpened e applichiamo un'animazione, detta di swipe.
private void GroupOpened(object sender, GroupViewOpenedEventArgs e)
{
for (int i = 0; i < e.ItemsControl.Items.Count; i++)
{
CreateStoryBoard(true, e.ItemsControl.ItemContainerGenerator.ContainerFromIndex(i)).Begin();
}
}Il metodo è semplicissimo: recuperiamo gli elementi vitalizzati nella jump-list, applichiamo l'animazione creata nel metodo CreateSoryboard e la eseguiamo.
Infine, dobbiamo riprodurre l'animazione alla chiusura della jumplist: in questo caso utilizziamo il gestore per l'evento GroupViewClosing, invocato al tap di un elemento della jump-list.
private void GroupClosing(object sender, GroupViewClosingEventArgs e)
{
e.Cancel = true;
int animationFinished = 0;
for (int i = 0; i < e.ItemsControl.Items.Count; i++)
{
Storyboard storyboard = CreateStoryBoard(false,
e.ItemsControl.ItemContainerGenerator.ContainerFromIndex(i));
storyboard.Completed += delegate
{
if ((++animationFinished) == e.ItemsControl.Items.Count)
{
AssociatedObject.CloseGroupView();
AssociatedObject.ScrollToGroup(e.SelectedGroup);
}
};
storyboard.Begin();
}
}In questo caso, il metodo è leggermente più complesso, in quanto è necessario gestire il termine dell'animazione per chiudere e spostarsi al gruppo selezionato solo quando tutte le animazioni sono terminate.
A questo punto il behavior è pronto ad essere utilizzato. In allegato è disponibile il codice completo pronto ad essere utilizzato.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Sfruttare la funzione REGEXP_SUBSTR di Sql Server per estrarre testo da un campo tramite regular expression
Validare i dati di una colonna JSON in SQL Server
Dallo sviluppo locale ad Azure con .NET Aspire
Bloccare il traffico di rete in uscita dal runner di GitHub
Monitorare le tabelle di Azure SQL Database con Change Event Streaming
Raggruppamento degli aggiornamenti di dipendenze tra directory in un monorepo con Dependabot
Running workloads and operations with Azure Kubernetes Service
Avviare rapidamente un container con Azure Container Apps Express
Keynote .NET Conference Italia 2025
Supporto semplificato per le left join in Entity Framework 10
Integrare un LLM in ASP.NET Core con Microsoft.Extensions.AI
Come automatizzare il download dei report di billing da GitHub Enterprise
I più letti di oggi
- Accedere a risorse e immagini in Windows Store app di Windows 8
- Effettuare il multi-checkout in linea nelle pipeline di Azure DevOps
- Esaminare documenti XML con namespace utilizzando LINQ to XML
- Alleggerire le applicazioni WPF sfruttando gli oggetti Freezable
- Permettere il Drag-and-drop solo su zone predefinite con Silverlight 2.0
- Consumare dati binari in realtime lato client con ASP.NET Core SignalR
- Personalizare l'icona e le funzionalità di un sito web per iOS e IE
- Esaminare documenti con namespace con LINQ e XDocument
- Accedere a dati esposti con WebService con Silverlight 1.0
- Effetto turnstile su tutte le pagine con il Windows Phone Toolkit


