【问题标题】:Using Caliburn in a WP7 UserControl throws exception在 WP7 UserControl 中使用 Caliburn 会引发异常
【发布时间】:2012-12-07 01:54:41
【问题描述】:

我正在尝试使用控件内部的 Caliburn Micro 为 Windows Phone 应用程序构建用户控件。引导程序通常设置在 App 资源中

  <Application.Resources>
     <local:AppBootstrapper x:Key="bootstrapper" />
  </Application.Resources>

我尝试在用户控件的 Xaml 中执行此操作。

 <UserControl.Resources>
     <local:AppBootstrapper x:Key="bootstrapper" />
 </UserControl.Resources>

但这会在组件加载时的初始化过程中引发异常。 LoadComponent 调用引发异常:“Microsoft.Phone.ni.dll 中发生了‘System.InvalidOperationException’类型的第一次机会异常”

应该在何时何地初始化引导程序?

【问题讨论】:

    标签: windows-phone-7 caliburn.micro


    【解决方案1】:

    由于您在 UserControl 上放置了引导程序,因此 PhoneApplicationService 可能已经实例化 - 您是否尝试将引导程序放在应用资源部分?

    CM 源代码显示,当引导程序初始化时,CM 创建了一个 PhoneApplicationService 的新实例,这看起来像问题,您的应用程序的根必须已经创建了一个实例。

    您是否有理由不能以标准方式(在应用资源中)使用 boostrapper?您的 App.xaml 是否包含 PhoneApplicationService 的初始化程序?

    编辑:

    您收到错误的 CM 源位于 PrepareApplication。例如

    protected override void PrepareApplication() {
            base.PrepareApplication();
    
                phoneService = new PhoneApplicationService();
                phoneService.Activated += OnActivate;
                phoneService.Deactivated += OnDeactivate;
                phoneService.Launching += OnLaunch;
                phoneService.Closing += OnClose;
    
                Application.ApplicationLifetimeObjects.Add(phoneService);
    
                if (phoneApplicationInitialized) {
                    return;
                }
    
                RootFrame = CreatePhoneApplicationFrame();
                RootFrame.Navigated += OnNavigated;
    
                phoneApplicationInitialized = true;
            }
    

    您可能只是将其子类化,而不是创建新的 PhoneApplicationService 而是重用现有的:

        /// <summary>
        /// A custom bootstrapper designed to setup phone applications.
        /// </summary>
        public class CustomPhoneBootstrapper : Bootstrapper {
        bool phoneApplicationInitialized;
        PhoneApplicationService phoneService;
    
        /// <summary>
        /// The root frame used for navigation.
        /// </summary>
        public PhoneApplicationFrame RootFrame { get; private set; }
    
        /// <summary>
        /// Provides an opportunity to hook into the application object.
        /// </summary>
        protected override void PrepareApplication(PhoneApplicationService phoneAppService, PhoneApplicationFrame rootFrame) {
            base.PrepareApplication();
    
            phoneService = phoneAppService;
            phoneService.Activated += OnActivate;
            phoneService.Deactivated += OnDeactivate;
            phoneService.Launching += OnLaunch;
            phoneService.Closing += OnClose;
    
            Application.ApplicationLifetimeObjects.Add(phoneService);
    
            if (phoneApplicationInitialized) {
                return;
            }
    
            RootFrame = rootFrame;
            RootFrame.Navigated += OnNavigated;
    
            phoneApplicationInitialized = true;
        }
    
        void OnNavigated(object sender, NavigationEventArgs e) {
            if (Application.RootVisual != RootFrame) {
                Application.RootVisual = RootFrame;
            }
        }
    
        /// <summary>
        /// Occurs when a fresh instance of the application is launching.
        /// </summary>
        protected virtual void OnLaunch(object sender, LaunchingEventArgs e) { }
    
        /// <summary>
        /// Occurs when a previously tombstoned or paused application is resurrected/resumed.
        /// </summary>
        protected virtual void OnActivate(object sender, ActivatedEventArgs e) { }
    
        /// <summary>
        /// Occurs when the application is being tombstoned or paused.
        /// </summary>
        protected virtual void OnDeactivate(object sender, DeactivatedEventArgs e) { }
    
        /// <summary>
        /// Occurs when the application is closing.
        /// </summary>
        protected virtual void OnClose(object sender, ClosingEventArgs e) { }
    }
    

    免责声明:不确定这是否会起作用,因为我从未开发过 Windows Phone,但据我所知,它应该做原始引导程序所做的事情,但跳过了应用程序和根框架的创建。您只需要提供应用程序和根框架(或者如果您可以从应用程序对象获取根框架,则可能只是应用程序 - 就像我说的,不知道有什么可能)

    【讨论】:

    • 在 WP7 应用程序中,用户控件没有 app.xaml。而且我不能将引导程序放在应用程序中,因为用户控件应该独立于使用它的应用程序。通常,这些应用程序将拥有自己的 PhoneApplicationService。所以我认为它不会起作用?
    • boostrapper 所做的只是初始化您的应用程序 - 如果您不需要初始化应用程序,那么可能有其他方法可以让 CM 将其约定应用于您的 UC 而无需尝试重​​新初始化应用程序。最简单的方法可能是对 CM 源进行 DL 并对代码进行小修改。我将在我的答案中发布详细信息
    • 我已经添加了一个答案 - 因为 PhoneBootstrapper 是公共的,所以您可以将其子类化并稍微更改发生的事情(而不是创建一个新的 PhoneApp 类,只需使用现有的类并让 CM 完成它挂钩等)。虽然我不确定Frame 的参考 - 但试试看
    【解决方案2】:

    它不打算在 UserControl 的资源中使用,所以我不能保证任何好的或坏的行为。引导程序应该在应用程序资源中使用,或者您可以直接在代码中实例化它。尝试在调用 InitializeComponent 之后在用户控件的 ctor 中创建它。

    【讨论】:

    • 我试过 AppBootstrapper bootstrapper = new AppBootstrapper();在控件的 Loaded Event 中,但它会引发相同的异常。
    • 内部异常是什么?异常堆栈的底部是什么意思?
    • 异常是:“System.InvalidOperationException:不支持创建多个 PhoneApplicationService 实例。\r\n 在 Microsoft.Phone.Shell.PhoneApplicationService..ctor()\r\n 在 Caliburn.Micro .PhoneBootstrapper.PrepareApplication()\r\n 在 Caliburn.Micro.BootstrapperBase.StartRuntime()\r\n 在 Caliburn.Micro.BootstrapperBase.Start()\r\n 在 Caliburn.Micro.Bootstrapper..ctor(布尔 useApplication )\r\n 在 Caliburn.Micro.PhoneBootstrapper..ctor()\r\n 在 CloudStorage.AppBootstrapper..ctor()\r\n 在 CloudStorage.UIControl.UI_Loaded(Object sender, RoutedEventArgs e)"
    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多