【问题标题】:Flow of initializing objects in XAML?在 XAML 中初始化对象的流程?
【发布时间】:2013-05-05 08:17:49
【问题描述】:

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

我期望的流程是:-

  • 首先创建MainPage。列表框已设置。
  • 用户将单击列表框的任何元素。 Itemclick 事件处理程序运行。它将设置静态变量(Mainpage.cs)来保存点击了哪个项目的信息并将用户导航到详细信息页面。
  • 在详细信息页面构造函数中,我已根据上一步中提到的静态变量的值将数据上下文设置为指向一些信息。
  • 它在大多数情况下都有效,但每 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 字节
  • [外部代码]
  • 主要更新: 我终于找到了漏洞。如果详细信息页面仍然处于活动状态,并且应用程序重新启动,则会出现问题。 这个问题有解决办法吗?

    【问题讨论】:

      标签: xaml windows-runtime winrt-xaml


      【解决方案1】:

      您可以通过 Navigate 调用传递有关需要在详细信息页面上显示的信息,并在 OnNavigatedTo 覆盖中设置 DataContext 以避免使用静态变量。除非您专门创建页面,否则不会创建页面,例如通过导航到一个。如果页面的 NavigationCacheMode 从默认值(禁用)更改,则可能不会重新创建它们,因此可以在导航调用期间重用页面实例。最终很难说出了什么问题,但它似乎在您的代码中,如果您不分享重现问题的示例,我们将无法帮助您。

      *编辑

      调试在MainPage 之前创建的Details 的一种方法是在Details 构造函数的开头添加此代码:

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

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

      查看matchFullDetails 是否曾经设置为null 的一种方法是搜索其分配(在Visual Studio 代码编辑器中将光标放在matchFullDetails 上并按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 中的暂停管理器调用并始终从主页开始,尽管这不是一个很好的体验,我不确定它是否满足应用认证。

      【讨论】:

      • 谢谢。也许 NavigationCacheMode 是问题所在。当我从 Visual Studio 重新启动应用程序时,它会影响吗?我的意思是 Visual Studio/RunTime 是否尝试缓存详细信息页面?我会尽快发布代码。会尽量保持相关性。
      • 我想知道如果 matchdetails 仅包含空值,是否说 Last() 可能会失败。此外,如果您的应用程序被暂停、终止并且您返回它并导航到您的详细信息页面,您的 MainPage 类可能从未被初始化。您是否有实际的异常详细信息,包括任何内部异常?
      • 捕获异常。用户代码未处理空引用异常。如果应用程序被暂停/终止,应用程序会自动转到 MainPage。
      • matchdetails 是 null 还是 matchdetails.Last()?
      • matchdetails 为空。我真的被困在了这一点上。真的不知道为什么它只是偶尔出现一次?如果至少每次都出现错误,我可以尝试不同的方法来查看它是否已被杀死。但这一个真的很令人沮丧。我尝试的每一个不同的事情,都认为“OK bug 现在可能已经消失了”,它又出现了。huhhhh :-(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      • 2018-02-10
      • 2013-06-27
      相关资源
      最近更新 更多