Событие MainWindow.Closing не всегда возникает в приложении Silverlight 4 OOB - PullRequest
6 голосов
/ 28 августа 2010

Я сделал довольно сложное приложение Silverlight 4 вне браузера. Одна из моих моделей основного вида добавляет обработчик событий к событию Application.Current.MainWindow.Closing. Это прекрасно работает, когда приложение изначально запущено. Может отменить операцию закрытия.

Однако, иногда после выполнения таких операций, как отображение и закрытие ChildWindow, событие закрытия MainWindow больше не вызывает мой обработчик.

В отладчике я добавил часы в базовый делегат события закрытия MainWindow. Это не ноль, прежде чем показывать ChildWindow. Затем иногда после закрытия ChildWindow, делегат является нулевым. Это объясняет, почему мой обработчик больше не вызывается. Но почему этот делегат обнуляется? И почему это происходит только изредка? Мое приложение не отменяет привязку моего обработчика событий.

Это делегат, которого я наблюдаю:

System.Windows.Application.Current.MainWindow.m_closingEvent

Другие вещи: я использую Caliburn Micro

Ответы [ 3 ]

8 голосов
/ 10 сентября 2010

У меня была точно такая же проблема.У нас есть большое приложение Silverlight, работающее на OOB.

По какой-то причине 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 в поле и проверить, решает ли это вашу проблему.

3 голосов
/ 31 августа 2010

Вместо того, чтобы подключиться к событию, почему бы не зарегистрировать сервис вместо этого?Создайте класс, который реализует IApplicationService и IApplicationLifetimeAware.Последний дает вам пару событий "onexiting" и "onexited".Вы помещаете сервис в приложение, указывая на него в разделе, который называется в вашем App.xaml.Я использовал это для многих проектов, и у меня никогда не было проблем с тем, что методы exiting не вызывались.

1 голос
/ 04 апреля 2011

Хорошо, после того, как выдернул мои волосы и много фальстартов Я наконец нашел ответ - похоже, это известная ошибка с событиями закрытия, 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;
        }
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...