Как создать диалоговое окно для запроса пользователю опции "Да/Нет" в WPF

Я знаю, как это сделать в Windows Form App, но я никак не мог найти это в приложении WPF. Как я могу представить пользователю блокирующий DialogBox с параметром "Да/Нет" и получить/обработать ответ от пользователя?

Ответ 1

Здесь пример:

string sMessageBoxText = "Do you want to continue?";
string sCaption = "My Test Application";

MessageBoxButton btnMessageBox = MessageBoxButton.YesNoCancel;
MessageBoxImage icnMessageBox = MessageBoxImage.Warning;

MessageBoxResult rsltMessageBox = MessageBox.Show(sMessageBoxText, sCaption, btnMessageBox, icnMessageBox);

switch (rsltMessageBox)
{
    case MessageBoxResult.Yes:
    /* ... */
    break;

    case MessageBoxResult.No:
    /* ... */
    break;

    case MessageBoxResult.Cancel:
    /* ... */
    break;
}

Ответ 2

Обратите внимание, что в то время как ответ Radu работает, вы не можете применять стили WPF к MessageBox.

Я применил другой подход к этой проблеме.

Я создал класс, который будет служить в качестве модели представления для моего окна сообщений, и я создал стиль для того, как я хотел, чтобы мое окно появилось. Позже в коде я создал новое окно, установил его DataContext в экземпляр моей модели просмотра и установил свойство Window Style в стиле, который я создал для окна.

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

Например, здесь показана модель диалогового окна:

Public Class MyDialogViewModel
  Public Event Closed()

  Public Property Message As String

  Public Property Cancel As MyNamespace.RelayCommand
  Public Property Close As MyNamespace.RelayCommand
  Public Property WasCancelled As Boolean

  Public Sub New()
    WasCancelled = True
    Cancel = New MyNamespace.RelayCommand(AddressOf CancelClicked)
    Close = New MyNamespace.RelayCommand(AddressOf CloseClicked)
  End Sub

  Private Sub CancelClicked()
    RaiseEvent Closed()
  End Sub
  Private Sub CloseClicked()
    WasCancelled = False
    RaiseEvent Closed()
  End Sub
End Class

Вот мой стиль для базового окна "сообщение":

    <Style x:Key="myMessageStyle" TargetType="{x:Type myNameSpace:CustomDialogWindow}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <ControlTemplate.Resources>
                        <Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
                            <Setter Property="Width" Value="100"/>
                            <Setter Property="Height" Value="25"/>
                        </Style>
                    </ControlTemplate.Resources>
                    <Border >
                        <DockPanel Margin="10,10,0,10">
                            <TextBlock Text="{Binding Message}" Width="Auto" TextWrapping="WrapWithOverflow" DockPanel.Dock="Top" 
                                       Margin="10"
                                       Foreground="{StaticResource MyMessageBoxForegroundColor}"/>
                            <DockPanel Margin="5,0,0,0" DockPanel.Dock="Bottom">
                                <Button Content="Ok" Command="{Binding Close}" ></Button>
                                <Button Content="Cancel" Command="{Binding Cancel}"  HorizontalAlignment="Stretch"></Button>
                            </DockPanel>
                        </DockPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

My CustomDialogWindow - это просто окно, в котором нет ничего:

(XAML)

<Window x:Class="CustomDialogWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CustomDialogWindow"
        SizeToContent="WidthAndHeight">

</Window>

И в CustomDialogWindow у меня есть следующий код, чтобы окно закрывалось, когда пользователь нажимает кнопку "Отменить" или "ОК":

Public Class CustomDialogWindow 

    Private Sub CustomDialogWindow_DataContextChanged(ByVal sender As Object, ByVal e As System.Windows.DependencyPropertyChangedEventArgs) Handles Me.DataContextChanged
        Dim dContext As MyDialogViewModel= TryCast(DataContext, MyDialogViewModel)
        If dContext IsNot Nothing Then
            AddHandler DirectCast(DataContext, MyDialogViewModel).CloseWindow, AddressOf CloseWindow
        End If
    End Sub
    Private Sub CloseWindow()
        Me.Close()
    End Sub
End Class

Теперь, когда мне нужно использовать окно, я просто создаю новый CustomDialogWindow, устанавливаю его DataContext в новый экземпляр класса DialogViewModel и устанавливаю его в стиле myMessageStyle:

Dim cdw As New CustomDialogWindow
Dim dvm As New DialogViewModel
dvm.Message = "Hello World!"
cdw.DataContext = dvm
cdw.ShowDialog()

If dvm.WasCancelled = False Then 
  '....'
End If

Причина, по которой мне нравится этот подход, заключается в том, что я наследую от MyDialogViewModel и предоставляю больше свойств, чтобы, например, я мог отображать кучу вариантов для выбора пользователем. Я просто поставляю пользовательские стили для каждого типа окна, которое я хочу отобразить (обязательно привязав соответствующие свойства). Как я уже сказал, он очень гибкий и довольно простой в реализации.

Ура!

-Frinny