Windows Phone 8 Panorama SelectionChanged & Databinding

前端 未结 2 1892
别那么骄傲
别那么骄傲 2020-12-06 02:12

I wrote an app for Windows Phone 7, recently I\'ve upgraded it to Windows Phone 8 and I plan on adding some features. Unfortunately, I\'ve run into a problem immediately af

相关标签:
2条回答
  • 2020-12-06 02:51

    The Panorama control in WP8 has a known databinding bug. The symptoms of the bug are that SelectionChanged doesn't fire, SelectedIndex & SelectedItem aren't reliable and that back navigation into a page with Panorama resets the panorama selected item.

    For example, the following code sample will never fire the MessageBox and SelectedIndex & SelectedItem won't indicate the correct expected values.

    <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; }
    }
    

    One obvious fix will be to manually initialize PanoramaItems in code-behind.

    Another solution would be to change our collection from typed to untyped, and add the following code snippet to our bounded data class. So let's change our code from ObservableCollection<Cow> to ObservableCollection<object> and add some code to the Cow class:

    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();
        }
    }
    

    Now, when we run this code snippet we can see SelectionChanged fires as expected with the correct SelectedIndex values:

    Panorama firing the SelecitonChanged event with the correct SelectedIndex Panorama firing the SelecitonChanged event with the correct SelectedIndex

    0 讨论(0)
  • 2020-12-06 02:58

    Just a minor tip for anyone who has the ViewModel in a Portable Class Library - I put this code in the base class for my viewmodels:

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

    This solved the problem for me. As for the comment from @Sopuli - I definitely still have this problem on the WP8 devices I have tested. (Nokia Lumia 920, WP8.0.10517.150)


    A VB.NET version:

    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
    
    0 讨论(0)
提交回复
热议问题