Исключение - DialogResult можно установить только после того, как окно будет создано и показано как диалоговое окно.

У меня проблема с закрытием диалога, но он отображается только во второй раз, и только при закрытии определенным образом.

В диалоговом окне есть единственная кнопка, которая объявлена ​​как кнопка отмены, т. е. имеет значение IsCancel="True". Нет обработчика события нажатия кнопки. Я могу показать этот диалог и закрыть его каждый раз, либо нажав кнопку, либо нажав клавишу Escape, и с этим нет проблем, он работает каждый раз.

У меня также есть концепция сеанса пользователя. Если сеанс пользователя истекает, все открытые диалоги должны автоматически закрываться. Это отлично работает, когда срок действия сеанса истекает, когда диалоговое окно отображается в первый раз, но если диалоговое окно уже было показано один раз и либо было закрыто путем явного нажатия кнопки, либо до истечения срока действия сеанса, то по истечении срока действия следующего сеанса пока отображается диалоговое окно, я получаю исключение «DialogResult может быть установлено только после того, как окно будет создано и показано как диалоговое окно».

Это очень любопытно, так как я могу посмотреть DialogResult диалогового окна до истечения срока действия второго сеанса, и он равен нулю. Когда я устанавливаю точку останова в момент истечения срока действия сеанса и собираюсь установить DialogResult, для DialogResult уже устанавливается значение false. Я понятия не имею, как это становится ложным.

Я использую Unity и задаюсь вопросом, дает ли он мне один и тот же экземпляр диалога каждый раз. Но если бы это было так, разве DialogResult не стал бы ложным, как только я разрешил ссылку на диалог? Это не так, это нуль, как я и ожидал.

Я просмотрел это, это, это и this, но ни один из них не помогает.

Здесь я получаю ссылку и показываю диалог

public void ShowLoginBarcode(string username) {
    BarcodeLoginForm frm = _Unity.Resolve<BarcodeLoginForm>();
    frm.Owner = Application.Current.MainWindow;
    BarcodeLoginVM vm = frm.ViewModel;
    vm.Username = username;
    frm.ShowDialog();
}

Вот xaml.cs для диалога

public partial class BarcodeLoginForm : Window, ICloseableDialog {
    public void CloseDialog(bool dialogResult) {
        DialogResult = dialogResult;
    }

    private void Window_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) {
        // register the view with the view model, so the view model can call the view's CloseDialog method
        if (e.OldValue != null)
            ((BarcodeLoginVM)e.OldValue).SetView(null);
        if (e.NewValue != null)
            ((BarcodeLoginVM)e.NewValue).SetView(this);
    }
}

Вот часть модели представления.

public void SetView(ICloseableDialog view) {
    _Dialog = view;
}

private void Session_OnTimeoutChange(object sender, EventArgs e) {
    if (_Session.HasExpired)
        CloseDialog(false);
}

private void CloseDialog(bool dialogResult) {
    _Dialog?.CloseDialog(dialogResult);
}

Вот простейший набор шагов, которые показывают проблему:

  1. покажи диалог.
  2. нажмите кнопку закрытия, чтобы закрыть диалоговое окно. (В качестве альтернативы можно позволить сеансу истечь, чтобы он закрыл диалоговое окно.)
  3. показать диалог снова. (Если я смотрю на DialogResult, пока диалоговое окно видимо, оно равно null. Я добавил обработчик событий KeyPreview, чтобы поставить на него точку останова.)
  4. позволить сеансу истечь. В момент, когда DialogResult = dialogResult собирается выполниться в методе CloseDialog диалогового окна, для DialogResult уже установлено значение false.

Итак, есть идеи?

Изменить: я могу обойти проблему, изменив метод xaml.cs CloseDialog, чтобы проверить, что DialogResult имеет значение null, прежде чем присваивать значение, но я не понимаю, зачем это нужно. Как можно установить DialogResult перед выполнением этого кода?

public void CloseDialog(bool dialogResult) {
    if (!DialogResult.HasValue)
        DialogResult = dialogResult;
}

person Simes    schedule 25.05.2016    source источник
comment
Модальные диалоги должны быть удалены явно; это не происходит автоматически, как в немодальных диалогах. Это связано с тем, что вы должны иметь доступ к методу DialogResult, чего вы не могли бы сделать, если бы диалоговое окно было автоматически уничтожено.   -  person Cody Gray    schedule 28.05.2016
comment
Спасибо, но метода Window.Dispose() нет, и MSDN ничего не упоминает об этом требовании. msdn.microsoft. com/ru-ru/library/   -  person Simes    schedule 30.05.2016