ScrollViewer e ListPicker del Silverlight Toolkit: come farli andare d’accordo

Print Content | More

Recentemente mi è capitato di sviluppare un’applicazione in cui avessi la necessità di inserire un ListPicker all’interno di uno ScrollViewer. Una premessa, giusto per inquadrare lo scenario:

  • Il ListPicker è un controllo facente parte del Silverlight Toolkit che funge da sorta di dropdown: serve all’utente per selezionare una o più opzioni da una scelta di valori. Ad esempio, il controllo che, nella sezione Impostazioni, vi permette di selezionare il tema del vostro telefono è un ListPicker. Maggiori dettagli li trovate in questo post di un po’ di tempo fa.
  • Lo ScrollViewer di Silverlight è un controllo che ci permette di gestire le situazioni in cui il contenuto da mostrare è più lungo della dimensione dello schermo: inserendo dei controlli dentro uno ScrollViewer, l’utente potrà, con il dito, fare scrolling in giù e in su e vedere anche quelli non inizialmente visibili.

Con mio rammarico ho scoperto che questi due controlli non vanno d’accordo insieme: se inserite un ListPicker all’interno di uno ScrollViewer, il ListPicker cesserà di funzionare. Questo perchè l’evento touch dello ScrollViewer “vince” su quello del ListPicker: questo significa che riuscirete a fare lo scrolling, ma facendo tap sul ListPicker non accadrà nulla.

Per sperimentare il problema, vi basta creare un’applicazione, inserire in una pagina uno XAML di questo tipo e lanciarla:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <ScrollViewer>
        <StackPanel>
            <TextBlock Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ultrices metus congue nibh varius a egestas erat sodales. Donec pulvinar, lacus ac rhoncus blandit, purus enim laoreet nisi, id mollis erat nulla a eros. Aenean eu tincidunt urna. Proin ornare consequat sapien, eget sagittis ipsum scelerisque ut. Cras a augue est, ac egestas nibh. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec quis augue lectus, non viverra sem.
Quisque vel enim urna. Suspendisse potenti. Nullam sapien dolor, mattis at fringilla a, aliquam ac tortor. Phasellus in purus eu felis dignissim congue sed vel odio. Donec dignissim, mi vitae adipiscing fringilla, sapien urna cursus erat, eget euismod mi leo ut ligula. Fusce vitae leo sit amet dui viverra mattis. Nullam et ipsum sed nunc lacinia posuere. Maecenas ullamcorper arcu at lectus consequat nec viverra nibh vulputate. Nunc sem sapien, volutpat id scelerisque at, bibendum sed erat.
" TextWrapping="Wrap" />
            <toolkit:ListPicker>
                <toolkit:ListPicker.Items>
                    <sys:String>First item</sys:String>
                    <sys:String>Second item</sys:String>
                    <sys:String>Third item</sys:String>
                    <sys:String>Fourth item</sys:String>
                    <sys:String>Fifth item</sys:String>
                    <sys:String>Sixth item</sys:String>
                </toolkit:ListPicker.Items>
            </toolkit:ListPicker>
        </StackPanel>
    </ScrollViewer>
</Grid>

Notate il lungo testo fittizio che ho inserito: questo perchè il problema si presenta solo nel momento in cui il ListPicker è inserito in uno ScrollViewer con altri controlli che rendono necessario lo scrolling. In caso contrario, il problema non si verifica.

Per fortuna, trovare una soluzione è stato semplice, dato che non sono il primo ad essermi imbattuto nel problema: per risolverlo, avrete bisogno però del codice sorgente del progetto, scaricabile dal sito http://silverlight.codeplex.com, oppure potete scaricare direttamente la DLL ricompilata tramite il link che troverete in fondo al post.

La soluzione è infatti quella di effettuare una modifica al codice sorgente del toolkit, precisamente nel file ListPicker.cs, alla riga 881. Dovrete cambiare il blocco di codice:

if (IsValidManipulation(e.OriginalSource, e.ManipulationOrigin.X, e.ManipulationOrigin.Y) && 0 < Items.Count)
{
   if (Open())
   {
      e.Handled = true;
   }
}

con il seguente:

Point point = new Point(e.ManipulationOrigin.X, e.ManipulationOrigin.Y);
if (e.ManipulationContainer != e.OriginalSource)
{
   var trans = e.ManipulationContainer.TransformToVisual((UIElement)e.OriginalSource);
   point = trans.Transform(point);
}
 
if (IsValidManipulation(e.OriginalSource, point.X, point.Y) && 0 < Items.Count)
{
   if (Open())
   {
      e.Handled = true;
   }
}

E’ stato creato un work item su Codeplex per questo problema, quindi è probabile che nelle prossime versioni venga risolto. Per ora, potete tranquillamente utilizzare questo workaround!


Windows Phone , Silverlight Toolkit , ListPicker , ScrollViewer

0 comments

Related Post


(will not be published)
(es: http://www.mysite.com)