2010-08-28 3 views
6

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

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

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

Это делегат я смотрю:

System.Windows.Application.Current.MainWindow.m_closingEvent 

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

+0

Звучит как действительно хороший вопрос. Первая диагностика, которую я бы использовал, - это создать простое приложение OOB (без калибровки и т. Д.), Которое просто открывает и закрывает ChildWindows и сворачивает RootVisuals, чтобы увидеть, можно ли создать простой реестр. – AnthonyWJones

+0

Хорошо, у меня такая же проблема - как только я не открываю/закрываю ChildWindow, срабатывает событие Closing. Иногда, если у меня есть отладчик, он также срабатывает, но не всегда. Я попробовал ApplicationWrapper ниже без радости. Какие-либо предложения?! – Rodney

ответ

8

У меня была такая же проблема. У нас есть большое приложение 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 в поле и проверить, разрешает ли это вашу проблему.

+0

Я просто попробовал это, и кажется работать! Мне нужно будет проверить еще на нескольких машинах, но, похоже, вы решили это (и решили это просто!) Большое вам спасибо! Я отмечу это как ответ и награду свою награду в ближайшее время. –

+0

Я не могу заставить это работать - где класс IApplicationWrapper? Кажется, что это не в Silverlight 4, и Google возвращает очень мало информации об этом? – Rodney

+0

В структуре нет интерфейса IApplicationWrapper. Его просто интерфейс, который я написал, чтобы включить зависимость и усечение, независимо от того, что зависит от приложения. Но если вы не заботитесь о том, что вы можете просто скопировать оболочку приложения и инициализировать ее из вашего основного окна, я думаю. –

3

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

+0

Спасибо за ответ, но мне нужна возможность отменить выходное событие (после запроса пользователя). Этот интерфейс, похоже, не дает возможности для этого. –

+0

+1, Не потому, что его ответ на проблему под рукой, а потому, что это просто аккуратная вещь. Также просто слишком легко забыть объекты App Life, поэтому приятно напоминать, что вам не нужно делать все в App Start и Exit. – AnthonyWJones

+0

+1, искал аккуратное решение, что эта проблема. Приветствия. –

1

Ok, после вытаскивания моих волос и многие фальстарта I finally found the answer - это, кажется, известная ошибка с закрытием события, 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

+0

Спасибо @ Rodney, но я не вижу, где вы используете _mainWindow? К сожалению, ссылки на silverlight.net больше не работают. – float

+0

Также App.GetApp.MainWindow; GetApp неизвестен? – float

Смежные вопросы