silverlight windows-phone-7 windows-phone-8 panorama-control

silverlight - Windows Phone 8 Panorama SelectionChanged y Databinding



windows-phone-7 windows-phone-8 (2)

Escribí una aplicación para Windows Phone 7, recientemente la actualicé a Windows Phone 8 y planeo agregar algunas características. Lamentablemente, me he encontrado con un problema inmediatamente después de la actualización. La parte principal de la aplicación es un control de Panorama que está enlazado a datos. En SelectionChanged estoy buscando los datos para el nuevo PanoramaItem + 1 (preseleccionando los datos para que estén allí cuando la persona finalmente vaya al elemento). Eso funcionó bien en WP7 pero el evento SelectionChanged no se dispara con WP8.

He reproducido el problema con una nueva aplicación WP8 que no se actualizó y también está aislada de los controles de datos. Si agrego estáticamente PanoramaItems, el evento SelectionChanged se dispara bien.

¿Me estoy perdiendo algo o es solo un error en WP8? ¿Alguna solución alternativa recomendada?

Tengo un repositorio de GitHub con una muestra estática y una muestra de datos para mostrar qué funciona y qué no funciona. https://github.com/bthubbard/DatabindingIssues


El control Panorama en WP8 tiene un error conocido de enlace de datos. Los síntomas del error son que SelectionChanged no se activa, SelectedIndex y SelectedItem no son confiables y que la navegación hacia atrás en una página con Panorama restablece el elemento seleccionado de panorama.

Por ejemplo, el siguiente ejemplo de código nunca disparará el MessageBox y SelectedIndex & SelectedItem no indicará los valores correctos esperados.

<phone:Panorama x:Name="panorama" ItemsSource="{Binding}" SelectionChanged="Panorama_SelectionChanged_1"> <phone:Panorama.HeaderTemplate> <DataTemplate> <ContentControl Content="{Binding Name}" /> </DataTemplate> </phone:Panorama.HeaderTemplate> <phone:Panorama.ItemTemplate> <DataTemplate> <ContentControl Content="{Binding Name}" /> </DataTemplate> </phone:Panorama.ItemTemplate> </phone:Panorama>

private void MainPage_Loaded(object sender, RoutedEventArgs e) { this.DataContext = new ObservableCollection<Cow>() { new Cow("Foo"), new Cow("Bar"), new Cow("Baz") }; } private void Panorama_SelectionChanged_1(object sender, SelectionChangedEventArgs e) { MessageBox.Show("Panorama_SelectionChanged_1: " + panorama.SelectedIndex); } public class Cow { public Cow(string name) { Name = name; } public string Name { get; set; } }

Una solución obvia será inicializar manualmente PanoramaItems en código subyacente.

Otra solución sería cambiar nuestra colección de mecanografiados a sin tipo, y agregar el siguiente fragmento de código a nuestra clase de datos acotada. Cambiemos nuestro código de ObservableCollection<Cow> a ObservableCollection<object> y agreguemos algún código a la clase Cow :

private void MainPage_Loaded(object sender, RoutedEventArgs e) { this.DataContext = new ObservableCollection<object>() { new Cow("Foo"), new Cow("Bar"), new Cow("Baz") }; } public class Cow { public Cow(string name) { Name = name; } public string Name { get; set; } public override bool Equals(object obj) { if ((obj != null) && (obj.GetType() == typeof(PanoramaItem))) { var thePanoItem = (PanoramaItem)obj; return base.Equals(thePanoItem.Header); } else { return base.Equals(obj); } } public override int GetHashCode() { return base.GetHashCode(); } }

Ahora, cuando ejecutamos este fragmento de código, podemos ver los incendios SelectionChanged como se esperaba con los valores de SelectedIndex correctos:


Solo un pequeño consejo para cualquiera que tenga el ViewModel en una biblioteca de clases portátil: puse este código en la clase base para mis viewmodels:

if (Equals(obj.GetType().Name, "PanoramaItem")) { var datacontextProperty = obj.GetType().GetRuntimeProperty("DataContext"); var datacontext = datacontextProperty.GetValue(obj); return Equals(datacontext, this); }

Esto resolvió mi problema. En cuanto al comentario de @Sopuli, definitivamente todavía tengo este problema en los dispositivos WP8 que probé. (Nokia Lumia 920, WP8.0.10517.150)

Una versión de VB.NET:

Public Overrides Function Equals(obj As Object) As Boolean If Equals(obj.GetType.Name, "PanoramaItem") Then Dim datacontextProperty = System.Reflection.RuntimeReflectionExtensions.GetRuntimeProperty(obj.GetType, "DataContext") Dim datacontext = datacontextProperty.GetValue(obj) Return Equals(datacontext, Me) Else Return MyBase.Equals(obj) End If End Function