0

よくわかりませんが、デバッグに何時間も費やしたので、これは私が提供できる問題の最良の説明であるはずです。WinRT アプリを作成しています。メイン ページと詳細ページの 2 つのページがあります。Main Page コンストラクター内で、リストボックスを初期化しました。リストボックスのいずれかの要素をクリックすると、ユーザーは詳細ページに移動します。私はこれらすべてを学んでおり、デザインは最善ではないかもしれませんが、これが私がやったことです. MainPage.cs で静的変数を取得し、ユーザーがクリックした要素を指すように設定しました。詳細ページのコンストラクターで、この静的変数を使用して詳細ページ自体のデータコンテキストを設定しました。

私が期待している流れは次のとおりです:-

  • MainPage が最初に作成されます。リストボックスが設定されました。
  • ユーザーはリストボックスの要素のいずれかをクリックします。Itemclick イベント ハンドラーが実行されます。(Mainpage.cs の) 静的変数を設定して、クリックされた項目の情報を保持し、ユーザーを詳細ページに移動します。
  • 詳細ページ コンストラクターで、前の手順で説明した静的変数の値に基づいて、いくつかの情報を指すようにデータ コンテキストを設定しました。
  • ほとんどの場合は機能しますが、5 回ごとに 1 回、詳細ページのコンストラクターは、静的変数がまだ初期化されていないことを示す例外をスローします。アプリの起動時に詳細ページのコンストラクターが実行されるのはなぜですか? なぜ時々だけ?コンストラクターではなく、他のメソッドで詳細ページの DataContext を設定する必要がありますか?

    コードはやや複雑で、問題のドメインが多すぎるため、投稿を避けています。しかし、私が問題を説明できていない場合は、教えてください。できる限り関連性を保って投稿します。

    CODE:- これは、リストボックス内の項目がクリックされたときに呼び出されるメソッドです。ユーザーは詳細ページに移動します。

    private void overviewlistbox_Tapped_1(object sender, TappedRoutedEventArgs e)
    {
        MatchOverview selectedmatch = (sender as ListBox).SelectedItem as MatchOverview;
        matchFullDetails = new ObservableCollection<Match>();
    
        foreach (Match m in UpdateController.matchList)
        {
            if (m.matchDescription == selectedmatch.matchDesc)
            {
                matchFullDetails.Add(m);
                break;
            }
        }
    
        if(!(matchFullDetails.Count == 0))
            this.Frame.Navigate(typeof(Details)); 
    }
    

    これはメインページのコンストラクタです:-

    public static ObservableCollection<Match> matchFullDetails;
    
    public MainPage()
    {
        matchFullDetails = new ObservableCollection<Match>();
        this.InitializeComponent();
        UpdateController update = new UpdateController();  // Creating new object will update the overview_list of UpdateController(static list).
        overviewlistbox.ItemsSource = UpdateController.overview_list; 
    }
    

    そして、これは例外が発生する詳細ページのコンストラクターのコードです:-

    public static ObservableCollection<Match> matchdetails = new ObservableCollection<Match>();
    DispatcherTimer dtm_detailspage = null;
    
    public Details()
    {
        this.InitializeComponent();
        matchdetails = MainPage.matchFullDetails;       // matchdetails.Last<>() is take because we only need item which is added latest to the collection.
        if (matchdetails.Last<Match>().type == "TEST")  // Exception is thrown here--Initialization 
                                                        // error. When I check MainPage.matchFullDetails,
                                                        // no data is shown which means its not yet
                                                        // initialized. Also the exception is thrown either at 
                                                        // the start of the app, or when details page is visited. That too once in 4-5 times, not always.
        {
            matchdetails.Add(matchdetails.First<Match>() as TestMatch);
        }
    
        if (matchdetails.Last<Match>().type == "ODI")
        {
            matchdetails.Add(matchdetails.Last<Match>() as ODIMatch);
        }
    
        if (matchdetails.Last<Match>().type == "T20")
        {
            matchdetails.Add(matchdetails.Last<Match>() as T20Match);
        }                         
    }
    

    例外のスクリーンショット:- 実行時にスローされる例外

    バグ発生時のコール スタック データ:-

  • [Cricket Expert.exe!Cricket_Expert.Details.Details() 33 行目 + 0x5 バイト
  • 【外部コード】
  • Cricket Expert.exe!Cricket_Expert.Common.SuspensionManager.RestoreFrameNavigationState(Windows.UI.Xaml.Controls.Frame フレーム) 236 行目 + 0x5 バイト
  • Cricket Expert.exe!Cricket_Expert.Common.SuspensionManager.RestoreAsyn() 行 124 0x8 バイト
  • Cricket Expert.exe!Cricket_Expert.App.OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs args) 行 74 + 0x5 バイト
  • 【外部コード】
  • 主要な更新: ついに欠陥を発見しました。[詳細] ページがまだアクティブで、アプリを再起動すると、問題が発生します。この問題の解決策はありますか??

    4

    1 に答える 1

    1

    詳細ページに表示する必要があるものに関する情報を Navigate 呼び出しを介して渡し、OnNavigatedTo オーバーライドで DataContext を設定して、静的変数の使用を避けることができます。ページは、ページに移動するなど、具体的に作成しない限り作成されません。ページの NavigationCacheMode がデフォルト (無効) から変更されている場合、それらは再作成されない可能性があるため、ナビゲーションの呼び出し中にページのインスタンスを再利用できます。最終的に何が問題なのかを判断するのは困難ですが、コードに何か問題があるように思われます。問題を再現するサンプルを共有していただけない場合、私たちはあなたを助けることができませんでした.

    *編集

    Details以前に作成されたことをデバッグする 1 つの方法は、コンストラクターMainPageの先頭に次のコードを追加することです。Details

    if (MainPage.matchFullDetails == null)
    {
        System.Diagnostics.Debugger.Break();
    }
    

    次にCall Stack、Visual Studio のパネルを見て、どのように構築されるかを確認します。

    が null に設定されているかどうかを確認する 1 つの方法matchFullDetailsは、その割り当てを検索することです ( matchFullDetailsVisual Studio コード エディターにカーソルを置き、Shift + F12 キーを押します)。

    もう 1 つの方法は、matchFullDetails をプロパティにして、次のようにテストすることです。

    private static ObservableCollection<Match> _matchFullDetails;
    public static ObservableCollection<Match> matchFullDetails
    {
        get
        {
            return _matchFullDetails;
        }
        set
        {
            if (value == null)
            {
                System.Diagnostics.Debugger.Break();
            }
    
            _matchFullDetails = value;
        }
    }
    

    *編集2

    次のように、静的コンストラクターで静的プロパティを初期化できます。

    public static ObservableCollection<Match> matchFullDetails;
    
    static MainPage()
    {
        matchFullDetails = new ObservableCollection<Match>();
    }
    
    public MainPage()
    {
        this.InitializeComponent();
        UpdateController update = new UpdateController();  // Creating new object will update the overview_list of UpdateController(static list).
        overviewlistbox.ItemsSource = UpdateController.overview_list; 
    }
    
    • これにより、null 参照の例外は回避されますが、問題全体は解決されません。アプリが中断されて再開された場合、完全な状態を復元する必要があり、アプリが中断されたときに matchFullDetails コレクションをシリアル化してディスクに保存する必要があるようです。または、App.xaml.cs の一時停止マネージャーの呼び出しを単に無視して、常にホームページから開始することもできますが、これはあまり良いエクスペリエンスではなく、アプリの認定を満たすかどうかはわかりません。
    于 2013-04-30T17:42:18.190 に答える