/// <summary>
        /// Shows the "Save Changes" dialog for a document that is about to be closed and saves the
        /// document if required.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <returns>
        /// <see langword="true"/> if all changes are saved or can be discarded; otherwise
        /// <see langword="false"/> if there are still changes that need to be saved.
        /// </returns>
        /// <remarks>
        /// This method checks if the document is modified and can be saved. If this is the case a
        /// dialog is displayed that tells the user that the document is about to close and asks if
        /// any changes should be saved or discarded, or if any close operation should be canceled.
        /// If necessary, <see cref="Save"/> is called automatically.
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="document"/> is <see langword="null"/>.
        /// </exception>
        public bool PromptSaveChanges(Document document)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (!document.IsModified || !document.DocumentType.IsSavable)
            {
                return(true);
            }

            // Ask the user.
            var saveChangesDialog = new SaveChangesViewModel
            {
                ModifiedDocuments = new[] { document },
                DisplayName       = Editor.ApplicationName,
            };

            _windowService.ShowDialog(saveChangesDialog);

            if (saveChangesDialog.SaveChangesDialogResult == SaveChangesDialogResult.SaveAndClose)
            {
                Logger.Info(CultureInfo.InvariantCulture, "Saving document \"{0}\".", document.GetName());
                return(Save(document));
            }

            if (saveChangesDialog.SaveChangesDialogResult == SaveChangesDialogResult.CloseWithoutSaving)
            {
                Logger.Info(CultureInfo.InvariantCulture, "Discarding changes of document \"{0}\".", document.GetName());
                return(true);
            }

            Debug.Assert(saveChangesDialog.SaveChangesDialogResult == SaveChangesDialogResult.Cancel);
            Logger.Info(CultureInfo.InvariantCulture, "Closing of document canceled by user.");
            return(false);
        }
        private async Task <bool> CloseAllDocumentsButAsync(Document excludedDocument)
        {
            if (excludedDocument == null)
            {
                Logger.Info("Closing all documents.");
            }
            else
            {
                Logger.Info(CultureInfo.InvariantCulture, "Closing all documents except: \"{0}\".", excludedDocument.GetName());
            }

            // Collect all documents that need to be saved.
            var modifiedDocuments = _documents.Where(document => document != excludedDocument &&
                                                     document.IsModified &&
                                                     document.DocumentType.IsSavable)
                                    .ToArray();

            // Do we need to save the documents before closing them?
            if (modifiedDocuments.Length > 0)
            {
                var saveChangesDialog = new SaveChangesViewModel
                {
                    ModifiedDocuments = modifiedDocuments,
                    DisplayName       = Editor.ApplicationName,
                };
                _windowService.ShowDialog(saveChangesDialog);

                if (saveChangesDialog.SaveChangesDialogResult == SaveChangesDialogResult.SaveAndClose)
                {
                    foreach (var document in modifiedDocuments)
                    {
                        bool success = Save(document);
                        if (!success)
                        {
                            // The save operation failed or was canceled. --> Abort!
                            Logger.Info("Save operation failed or was canceled by user. Canceling close operation");
                            return(false);
                        }
                    }
                }
                else if (saveChangesDialog.SaveChangesDialogResult == SaveChangesDialogResult.CloseWithoutSaving)
                {
                    Logger.Info("Discarding changes of remaining document.");
                }
                else
                {
                    Debug.Assert(saveChangesDialog.SaveChangesDialogResult == SaveChangesDialogResult.Cancel);
                    Logger.Info("Close operation canceled by user.");
                    return(false);
                }
            }

            // Close all documents
            foreach (var document in _documents.ToArray())
            {
                if (document != excludedDocument)
                {
                    Close(document, true);

                    // Redraw GUI and keep app responsive.
                    await Dispatcher.Yield();
                }
            }

            return(true);
        }