Заставить MessageBox находиться поверх окна приложения в .net/WPF

В моем приложении WPF я иногда поднимал System.Windows.MessageBox. Когда он изначально отображается, он отображается поверх моего главного окна приложения, как я и хотел. Есть ли способ заставить его ВСЕГДА оставаться в верхней части главного окна? Моя проблема заключается в том, что когда отображается MessageBox, пользователи могут затем щелкнуть главное окно приложения и вывести его на передний план, что означает, что MessageBox становится невидимым. В этом случае пользователь может не осознавать, что оно есть, или забыть о нем, и для него основное приложение кажется зависшим.

Я читал несколько тем об этом, но ни одна из них не решила проблему для меня.

Я должен добавить, что поток, размещающий MessageBox, может не быть потоком пользовательского интерфейса. Спасибо, Том.


person Tom Davies    schedule 10.04.2012    source источник


Ответы (3)


Используйте версию MessageBox.Show, которая принимает "владельца" окна и передает ваше окно.

MessageBox.Show(Application.Current.MainWindow, "Im always on top - of the main window");

Если вы, возможно, не в потоке пользовательского интерфейса, попробуйте:

string msg="Hello!";
if (Application.Current.Dispatcher.CheckAccess()) {
    MessageBox.Show(Application.Current.MainWindow, msg);
}
else {
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(()=>{
        MessageBox.Show(Application.Current.MainWindow, msg);
    }));
}

Вы можете:
1. Invoke заблокировать поток до тех пор, пока MessageBox не будет закрыт ИЛИ
2. BeginInvoke в этом случае код вашего потока будет продолжать выполняться, но поток пользовательского интерфейса будет заблокирован MessageBox до его закрытия).

person Ricibob    schedule 10.04.2012
comment
Есть ли другой способ сделать это, если поток, создающий MessageBox, НЕ является потоком пользовательского интерфейса (т.е. не потоком, которому принадлежит MainWindow)? - person Tom Davies; 10.04.2012
comment
Ах, теперь эта информация должна была быть в начальном вопросе - я предлагаю добавить ее прямо сейчас! - person Ricibob; 10.04.2012
comment
@Ricibob: однажды я использовал этот подход для отправки сообщений в строку состояния вместо того, чтобы открывать окно сообщения. - person Robin Maben; 10.04.2012
comment
@TomDavies Я тестировал это с помощью Invoke и BeginInvoke, и в обоих случаях он отлично работает (с разным поведением блокировки). - person Ricibob; 10.04.2012
comment
@TomDavies Если вы используете больше, чем просто поток пользовательского интерфейса в WPF, это было бы хорошей идеей ;-) Здесь есть некоторый фон диспетчера: stackoverflow.com/questions/7839296/ - person Ricibob; 10.04.2012
comment
У меня была эта проблема, и я наткнулся на эту публикацию. После долгих испытаний я определил, что моя проблема заключалась исключительно в том, что он не вызывал окно сообщения в потоке пользовательского интерфейса. Прохождение через окно не имело к этому никакого отношения. Предполагая, что у вас отображается только главное окно, и вы не пытаетесь вызвать окно сообщения из другого окна, но оно принадлежит главному окну, вызов в потоке пользовательского интерфейса должен исправить это, и вам не нужно передавать окно в MessageBox.Show(). - person BrianVPS; 01.04.2014
comment
Как я могу добавить к этому заголовок, кнопку сообщения, значок? - person mrid; 01.06.2019

Это быстрый способ разместить окно сообщений поверх окон приложения.

MessageBox.Show(this ,"Output text"));

person juni-j    schedule 10.12.2015

Внутри вашего "public partial class MainWindow : Window" поместите следующий код. Таким образом, Invoke запустит ваш код внутри потока пользовательского интерфейса.

void ShowErrorMessage(ERROR err)
{
    this.Dispatcher.Invoke((Action)(() =>
    {
        MessageBox.Show(err.description, err.code.ToString(), MessageBoxButton.OK, MessageBoxImage.Error);
    }));
}
person GMG    schedule 27.02.2014