开发者

MainWindow.Closing event not always raised in Silverlight 4 OOB app

I've made a rather complex Silverlight 4 out-of-browser application. One of my main view models adds an event handler to the Application.Current.MainWindow.Closing event. This works fine when the application is initially run. It is able to cancel the close operation.

However, sometimes after performing operations like showing and closing a ChildWindow, the MainWindow's Closing event is no longer calling my handler.

In the debugger, I added a watch to the MainWindow's underlying closing event delegate. It's not null before showing the ChildWindow. Then sometimes after the ChildWindow is closed the delegate is nu开发者_JS百科ll. This is explains why my handler is not called any more. But why is this delegate getting nulled? And why is it only happening occasionally? My application is not unbinding my event handler at any point.

This is the delegate I'm watching:

System.Windows.Application.Current.MainWindow.m_closingEvent

Other stuff: I'm using Caliburn Micro


I had the exact same problem. We have a large silverlight application running OOB.

For some reason the m_ClosingEvent was nulled after running for a while. I have not been able to find the cause of this issue but I think it may have something to do with us changing the root visual or all the child windows we show.

I´m using a class 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.. 
}

And the InvokeClosing method was never called. But when I changed it to

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... 
}

The m_ClosingEvent isn´t nulled.

So, try to just store the "initial" MainWindow in a field and check if that solves your problem.


Instead of hooking to the event, why not register a service instead? Create a class that implements IApplicationService and IApplicationLifetimeAware. The latter gives you an "onexiting" and "onexited" pair of events. You place the service in the application by pointing to it in a section called in your App.xaml. I've used this for many projects and never had an issue with the exiting methods not being called.


Ok, after pulling out my hair and many false starts I finally found the answer - it seems to be a known bug with the Closing event, OOB and ChildWindows open/closes...

The trick is to store a static reference to the Main Window:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜