27

Jan

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

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:


      
      
      
      
      
      First item
      Second item
      Third item
      Fourth item
      Fifth item
      Sixth item
      
      
      
      
      

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!

by Il blog di Matteo Pagani on 1/27/2012
Post archive