Best является полностью субъективным и зависит от многих контекстных переменных, но вот как я это делаю в стиле MVVM.
В вашей модели основного вида определите свойство
pubic ObservableCollection<AlertViewModel"> Alerts { get; private set; }
в моем случае AlertViewModel имеет только свойство «Message» и RelayCommand «Dismiss».
В XAML вашего основного представления добавьте
<Grid>
<all of my other other view controls>
<ItemsControl x:Name="AlertsControl" Opacity="50" ItemsSource="{Binding Alerts}"/>
</Grid>
Убедитесь, что это последний элемент в главном контейнере вашего основного вида. Это гарантирует, что он имеет самый высокий z-порядок и будет отображаться поверх всех других элементов управления.
Вот шаблон данных для этой модели вида
<DataTemplate DataType="{x:Type vm:AlertViewModel}">
<Border CornerRadius="10" Margin="3" Background="Red">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Margin="10" Grid.Column="0"
Command="{Binding ElementName=theWindow, Path=DataContext.DismissAlarmCommand}"
CommandParameter="{Binding}">Dismiss</Button>
<TextBlock Foreground="White" FontWeight="ExtraBold" Grid.Column="1"
Text="{Binding Message}" FontSize="20"
VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
</Grid>
</Border>
</DataTemplate>
Теперь
Alerts.Add( new AlertViewModel() { Message = "Danger Will Robinson! Danger!" } );
Появится ярко-красное окно оповещения в верхней части главной формы. Он не уходит, пока пользователь не нажмет «Отклонить»
Если вы хотите, чтобы он мигал, затемнялся или исчезал или подпрыгивал вверх и вниз, вы можете добавить анимацию в шаблон данных.
Вы можете использовать конвертер или данные для включения / отключения остальных элементов управления в привязке байтов приложения к AlertsControl.HasItems
Удачи.