LaVOZs

The World’s Largest Online Community for Developers

'; c# - How to open multiple windows in a queue, each window waiting for previous to close? - LavOzs.Com

I'm trying to create a primitive notifications system.

This is how I show my window:

var data = new NotificationData {
    Title = "New order",
    OrderId = "1"
}
var notification = new NotificationWindow(data);
    Activated += (s, e) => { notification.Owner = this; };
    notification.Show();

Then the NotificationWindow just displays provided data. But if there are multiple notifications, they all stack in one spot, I need them to appear after previous is closed.

I tried to use ShowDialog() instead and it did work - but the MainWindow hangs when notification is open. Running it in a different thread using Task.Run() causes notifications not to appear.

You need to register to the closed event and then check if another notification is queued.

The key is the ShowOrQueueNotification which checks if there is a notification present or not. If there is one present, queue the new one and when the notification is closed, you need to check if there is one queued.

I've made an example to show how to use a queue for it:


MainWindow.xaml

<Window x:Class="TestNotificationQueue.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestNotificationQueue"
        mc:Ignorable="d"
        Title="MainWindow" Height="158.868" Width="266.385">
    <Grid>
        <Border Background="Yellow" VerticalAlignment="Center" HorizontalAlignment="Center" BorderThickness="1" BorderBrush="Black" >
            <StackPanel Margin="20">
                <TextBox x:Name="TextBoxMessage" Width="192" />
                <Button Content="ShowNotification" Width="128" Height="24" Click="Button_Click" Margin="8"/>
            </StackPanel>
        </Border>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;

namespace TestNotificationQueue
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Queue<NotificationInfo> _notificationQueue = new Queue<NotificationInfo>();
        private NotificationWindow _currentNotificationWindow;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ShowOrQueueNotification(new NotificationInfo(TextBoxMessage.Text));
        }

        private void ShowOrQueueNotification(NotificationInfo notificationInfo)
        {
// ----->   If no notification is presented, create one.
            if (_currentNotificationWindow == null)
            {
                _currentNotificationWindow = new NotificationWindow(notificationInfo);
                _currentNotificationWindow.Closed += CurrentNotificationWindow_Closed;
                _currentNotificationWindow.Show();
            }
            else
// ----->       queue it.
                _notificationQueue.Enqueue(notificationInfo);
        }

        private void CurrentNotificationWindow_Closed(object sender, EventArgs e)
        {
// ----->   This is crucial, you need to set the current to null, else all new notification will be queued and never be presented.
            _currentNotificationWindow = null;

            if(_notificationQueue.Count > 0)
                ShowOrQueueNotification(_notificationQueue.Dequeue());
        }
    }
}

Notification.cs

namespace TestNotificationQueue
{
    public class NotificationInfo
    {
        public NotificationInfo(string message)
        {
            Message = message;
        }

        public string Message { get; }
    }
}

NotificationWindow.xaml

<Window x:Class="TestNotificationQueue.NotificationWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestNotificationQueue"
        mc:Ignorable="d"
        Title="NotificationWindow" Height="93.117" Width="239.4">
    <Grid>
        <TextBlock x:Name="TextBoxMessage" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="30" />
    </Grid>
</Window>

NotificationWindow.xaml.cs

using System.Windows;

namespace TestNotificationQueue
{
    /// <summary>
    /// Interaction logic for NotificationWindow.xaml
    /// </summary>
    public partial class NotificationWindow : Window
    {
        public NotificationWindow(NotificationInfo notificationInfo)
        {
            InitializeComponent();
            TextBoxMessage.Text = notificationInfo.Message;
        }
    }
}
Related
How do you handle multiple submit buttons in ASP.NET MVC Framework?
How should the ViewModel close the form?
How to hide close button in WPF window?
Modal dialog focus problems on WPF application
Who owns the process / main thread?
There is already an open DataReader associated with this Command which must be closed first
How do I open a second window from the first window in WPF?
Cannot use a DependencyObject that belongs to a different thread than its parent Freezable - prism
Application hang when opening new window; error messages indicate it is a stack overflow
serial port event not firing after opening the form using showDialog() method in c# windows form application