Dlaczego niektóre odpowiedzi na tej stronie są błędne!
Głównie:
- Okno nie powinno przyciągać fokusa od żadnego innego okna, gdy zostanie aktywowane;
- Okno nie powinno aktywować swojego rodzica, gdy jest wyświetlane;
- Okno powinno być kompatybilne z Citrix.
Rozwiązanie MVVM
Ten kod jest w 100% zgodny z Citrix (bez pustych obszarów ekranu). Jest testowany zarówno z normalnym WPF, jak i DevExpress.
Ta odpowiedź jest przeznaczona dla każdego przypadku użycia, w którym chcemy małe okno powiadomienia, które zawsze znajduje się przed innymi oknami (jeśli użytkownik wybierze to w preferencjach).
Jeśli ta odpowiedź wydaje się bardziej złożona niż inne, to dlatego, że jest to solidny kod na poziomie przedsiębiorstwa. Niektóre inne odpowiedzi na tej stronie są proste, ale w rzeczywistości nie działają.
XAML - właściwość dołączona
Dodaj tę dołączoną właściwość do dowolnej UserControl
w oknie. Załączona nieruchomość:
- Poczekaj, aż
Loaded
zdarzenie zostanie uruchomione (w przeciwnym razie nie będzie mógł przeglądać drzewa wizualnego w celu znalezienia okna nadrzędnego).
- Dodaj moduł obsługi zdarzeń, który zapewnia, że okno jest widoczne, czy nie.
W dowolnym momencie możesz ustawić okno tak, aby było na wierzchu lub nie, odwracając wartość dołączonej właściwości.
<UserControl x:Class="..."
...
attachedProperties:EnsureWindowInForeground.EnsureWindowInForeground=
"{Binding EnsureWindowInForeground, Mode=OneWay}">
C # - Metoda pomocnicza
public static class HideAndShowWindowHelper
{
/// <summary>
/// Intent: Ensure that small notification window is on top of other windows.
/// </summary>
/// <param name="window"></param>
public static void ShiftWindowIntoForeground(Window window)
{
try
{
// Prevent the window from grabbing focus away from other windows the first time is created.
window.ShowActivated = false;
// Do not use .Show() and .Hide() - not compatible with Citrix!
if (window.Visibility != Visibility.Visible)
{
window.Visibility = Visibility.Visible;
}
// We can't allow the window to be maximized, as there is no de-maximize button!
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
window.Topmost = true;
}
catch (Exception)
{
// Gulp. Avoids "Cannot set visibility while window is closing".
}
}
/// <summary>
/// Intent: Ensure that small notification window can be hidden by other windows.
/// </summary>
/// <param name="window"></param>
public static void ShiftWindowIntoBackground(Window window)
{
try
{
// Prevent the window from grabbing focus away from other windows the first time is created.
window.ShowActivated = false;
// Do not use .Show() and .Hide() - not compatible with Citrix!
if (window.Visibility != Visibility.Collapsed)
{
window.Visibility = Visibility.Collapsed;
}
// We can't allow the window to be maximized, as there is no de-maximize button!
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
window.Topmost = false;
}
catch (Exception)
{
// Gulp. Avoids "Cannot set visibility while window is closing".
}
}
}
Stosowanie
Aby tego użyć, musisz utworzyć okno w swoim ViewModel:
private ToastView _toastViewWindow;
private void ShowWindow()
{
if (_toastViewWindow == null)
{
_toastViewWindow = new ToastView();
_dialogService.Show<ToastView>(this, this, _toastViewWindow, true);
}
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(_toastViewWindow);
HideAndShowWindowHelper.ShiftWindowIntoForeground(_toastViewWindow);
}
private void HideWindow()
{
if (_toastViewWindow != null)
{
HideAndShowWindowHelper.ShiftWindowIntoBackground(_toastViewWindow);
}
}
Dodatkowe linki
Aby dowiedzieć się, jak upewnić się, że okno powiadomień zawsze przesuwa się z powrotem na widoczny ekran, zobacz moją odpowiedź: W WPF, jak przenieść okno na ekran, jeśli jest poza ekranem? .