9

Windows Phone 7用のアプリを作成しました。最近、Windows Phone 8にアップグレードし、いくつかの機能を追加する予定です。残念ながら、アップグレード直後に問題が発生しました。アプリの主要部分は、データバインドされたパノラマコントロールです。SelectionChangedで、新しいPanoramaItem + 1のデータをフェッチしています(データを事前に選択して、人が最終的にアイテムに移動したときにそこにあるようにします)。これはWP7では正常に機能しましたが、SelectionChangedイベントはWP8では発生しません。

アップグレードされておらず、データバインドされたコントロールにも分離されている新しいWP8アプリで問題を再現しました。静的にPanoramaItemsを追加すると、SelectionChangedイベントが正常に発生します。

私は何かが足りないのですか、それともこれはWP8の単なるバグですか?推奨される回避策はありますか?

静的サンプルとデータバインドされたサンプルを含むGitHubリポジトリがあり、何が機能し、何が機能しないかを示しています。 https://github.com/bthubbard/DatabindingIssues

4

2 に答える 2

18

WP8のPanoramaコントロールには、既知のデータバインディングのバグがあります。バグの症状は、SelectionChangedが起動しないこと、SelectedIndexとSelectedItemが信頼できないこと、Panoramaを使用してページに戻るナビゲーションでパノラマ選択されたアイテムがリセットされることです。

たとえば、次のコードサンプルはMessageBoxを起動せず、SelectedIndex&SelectedItemは正しい期待値を示しません。

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

明らかな修正の1つは、コードビハインドでPanoramaItemsを手動で初期化することです。

別の解決策は、コレクションを型付きから型なしに変更し、次のコードスニペットを制限付きデータクラスに追加することです。ObservableCollection<Cow>それでは、コードをからに変更して、クラスObservableCollection<object>にコードを追加しましょう。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();
    }
}

これで、このコードスニペットを実行すると、正しいSelectedIndex値で期待どおりにSelectionChangedが起動することがわかります。

正しいSelectedIndexでSelecitonChangedイベントを発生させるパノラマ 正しいSelectedIndexでSelecitonChangedイベントを発生させるパノラマ

于 2013-01-11T00:18:46.993 に答える
2

ポータブルクラスライブラリにViewModelを持っている人のためのちょっとしたヒント-私はこのコードをビューモデルの基本クラスに入れました:

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

これで問題は解決しました。@Sopuliからのコメントについては、テストしたWP8デバイスでまだこの問題が発生しています。(Nokia Lumia 920、WP8.0.10517.150)


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
于 2014-03-29T13:55:48.073 に答える