2010-08-28 99 views
6

我制作了一个相当复杂的Silverlight 4浏览器外应用程序。我的一个主视图模型向Application.Current.MainWindow.Closing事件添加了一个事件处理程序。 当应用程序最初运行时,这工作正常。它可以取消关闭操作。MainWindow.Closing事件并非总是在Silverlight 4中引发OOB应用程序

但是,有时执行像显示和关闭一个ChildWindow操作后,MainWindow的Closing事件不再调用我的处理程序。

在调试器中,我向MainWindow的底层关闭事件委托添加了一个监视。在显示ChildWindow之前它不是空的。然后有时 ChildWindow关闭后委托为空。这解释了为什么我的处理程序不再被调用。但是,为什么这个代表被禁止?为什么它只是偶尔发生? 我的应用程序不是在任何时候解除绑定我的事件处理程序。

这是委托我看:

System.Windows.Application.Current.MainWindow.m_closingEvent 

其他的东西:我使用的是卡利微

+0

听起来像一个非常好的问题。我首先使用的诊断是创建一个简单的OOB应用程序(不需要校准等),只需打开和关闭ChildWindows并将RootVisuals交换出来以查看是否可以创建简单的repro。 – AnthonyWJones 2010-08-28 16:21:41

+0

好的,我有同样的问题 - 只要我不打开/关闭ChildWindow,那么关闭事件触发。有时候,如果我连接了调试器,它也会启动,但并非总是如此。我尝试了下面的ApplicationWrapper,没有任何快乐。有什么建议么?! – Rodney 2011-04-04 04:30:14

回答

8

我有完全相同的问题。我们有一个运行OOB的大型Silverlight应用程序。

出于某种原因,m_ClosingEvent在运行一段时间后是零。我一直无法找到这个问题的原因,但我认为这可能与我们改变根视觉或我们展示的所有子窗口有关。

我正在使用ApplicationWrapper类。

public class ApplicationWrapper : IApplicationWrapper 
{ 
    public void Initialize() 
    { 
    HookCloseEvent(true); 
    } 
    private void HookCloseEvent(bool hook) 
    { 
    if (hook && IsRunningOutOfBrowser) 
    { 
     Application.Current.MainWindow.Closing += OnClosing; 
    } 
    else 
    { 
     if (IsRunningOutOfBrowser) 
     { 
     Application.Current.MainWindow.Closing -= OnClosing; 
     } 
    } 
    } 
    private void OnClosing(object sender, ClosingEventArgs e) 
    { 
    InvokeClosing(e); 
    } 

... etc.. 
} 

而InvokeClosing方法从未被调用过。但是当我将其更改为

public class ApplicationWrapper : IApplicationWrapper 
{ 
    private Window _mainWindow; 

    public void Initialize() 
    { 
    if(IsRunningOutOfBrowser) 
    { 
     _mainWindow = Application.Current.MainWindow; 
    } 
    HookCloseEvent(true); 
    } 

    private void HookCloseEvent(bool hook) 
    { 
    if (hook && IsRunningOutOfBrowser) 
    { 
     _mainWindow.Closing += OnClosing; 
    } 
    else 
    { 
     if (IsRunningOutOfBrowser) 
     { 
     _mainWindow.Closing -= OnClosing; 
     } 
    } 
    } 

    private void OnClosing(object sender, ClosingEventArgs e) 
    { 
    InvokeClosing(e); 
    } 

... etc... 
} 

m_ClosingEvent未被清除。

因此,试着将“初始”MainWindow存储在一个字段中,并检查是否可以解决您的问题。

+0

我刚刚尝试了这一点,它似乎上班!我需要再测试几台机器,但看起来你已经解决了它(并且简单地解决它!)非常感谢你!我会将此标记为答案并尽快奖励您的赏金。 – 2010-09-10 07:32:33

+0

我无法得到这个工作 - IApplicationWrapper类在哪里?它似乎并不在Silverlight 4中,Google只能返回很少的信息? – Rodney 2011-03-28 01:34:37

+0

框架中没有IApplicationWrapper接口。它只是我写的一个接口,用于启用依赖注入和单元测试,以取决于应用程序打包程序。但是,如果你不关心,你可以复制应用程序包装,并从我的初始化mainwindow我猜。 – 2011-03-29 05:29:22

3

相反的钩挂的情况下,为什么不注册一个服务,而不是?创建一个实现IApplicationService和IApplicationLifetimeAware的类。后者给你一个“onexiting”和“onexited”事件。您可以通过在App.xaml中调用的部分中指定服务来将该服务放入应用程序中。我已经将它用于很多项目,并且从未遇到过未被调用的退出方法的问题。

+0

感谢您的回答,但我需要能够取消退出事件(在提示用户后)。该界面似乎没有提供一个选项。 – 2010-08-31 12:11:28

+0

+1,不是因为它是对手头问题的回答,而是因为它只是一个整洁的事情。此外,它很容易忘记App寿命对象,所以它很好被提醒,你不必在App Start和Exit中做所有事情。 – AnthonyWJones 2010-08-31 20:08:14

+0

+1,一直在寻找一个整洁的解决方案,那个问题。干杯。 – 2010-09-10 07:31:11

1

好吧,拉出我的头发,很多出师不利I finally found the answer之后 - 这似乎是一个已知的错误与Closing事件,OOB和ChildWindows打开/关闭......

关键是要存储的静态引用到主窗口:

public MainPage() 
{ 
    InitializeComponent(); 
    Loaded += MainPage_Loaded; 
} 

private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e) 
{ 
    //you have to store this to work around the bug 
    //http://forums.silverlight.net/forums/p/185664/424174.aspx 
    _mainWindow = App.GetApp.MainWindow; 

    App.GetApp.MainWindow.Closing += (s, e1) => 
    { 
     if (UIUtilities.ShowMessage("Would you like to exit AMT Mobile?", "Exit Application", MessageBoxButton.OKCancel) != MessageBoxResult.OK) 
     { 
      e1.Cancel = true; 
     } 
    }; 
} 
+0

谢谢。这正是我所需要的。 – xanadont 2011-08-05 05:13:24

+0

谢谢@Rodney,但我没有看到你在哪里使用_mainWindow?不幸的是,silverlight.net的链接不再工作。 – float 2016-03-17 07:37:20

+0

也App.GetApp.MainWindow; GetApp未知? – float 2016-03-17 08:31:05

相关问题