0

我不确定,但从我的调试时间来看,这应该是我能给出的对我的问题的最佳描述。我正在创建一个 WinRT 应用程序,有两个页面 - 主页和详细信息页面。在 Main Page 构造函数中,我初始化了一个列表框。单击列表框的任何元素时,用户将被带到详细信息页面。我只是在学习所有这些,设计可能不是最好的,但这就是我所做的。我在 MainPage.cs 中获取了一个静态变量,并将其设置为指向用户单击的元素。现在在详细信息页面的构造函数中,我使用这个静态变量来设置详细信息页面本身的数据上下文。

我期待的流程是:-

  • 首先创建 MainPage。列表框已设置。
  • 用户将单击列表框的任何元素。Itemclick 事件处理程序运行。它将设置静态变量(Mainpage.cs)来保存单击了哪个项目的信息并将用户导航到详细信息页面。
  • 在详细信息页面构造函数中,我根据上一步中提到的静态变量的值,将 datacontext 设置为指向一些信息。
  • 它在大多数情况下都有效,但每 5 次就会出现一次,详细信息页面构造函数会引发异常,说明静态变量尚未初始化。为什么在我启动应用程序时会运行详细信息页面的构造函数?为什么只是有时?我是否需要以其他方法而不是构造函数设置详细信息页面的 DataContext?

    就问题的领域而言,代码有点复杂,而且太多,所以我避免发布它。但是,如果我无法解释问题,请告诉我,我会尽可能保持相关性发布它。

    代码:- 这是单击列表框中的项目时调用的方法-将用户带到详细信息页面。

    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 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之前创建的调试方法之一是在构造函数MainPage的开头添加此代码:Details

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

    然后查看Call StackVisual Studio 中的面板,了解它是如何构建的。

    查看是否matchFullDetails曾经设置为 null 的一种方法是搜索其分配(将光标放在matchFullDetailsVisual Studio 代码编辑器中并按 Shift+F12)。

    另一种方法是将 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; 
    }
    
    • 这将防止空引用异常,但不会整体解决您的问题。当您的应用程序被暂停和恢复时 - 您必须恢复完整状态,并且当您的应用程序暂停时,您的 matchFullDetails 集合似乎需要序列化并保存到磁盘。或者,您可以简单地忽略 App.xaml.cs 中的暂停管理器调用并始终从主页开始,尽管这不是一个很好的体验,我不确定它是否满足应用程序认证。
    于 2013-04-30T17:42:18.190 回答