I am developping a .net desktop WPF app in MVVM pattern using Visual Studio. I want to add confirmation dialog and bind "yes" or "no" according to the user click. I made some research but solutions offered either is not appropriate for MVVM pattern or requires adding a lot of external packages which I dont want to. Could anyone help me to find a proper solution that solves my problem?
Asked
Active
Viewed 120 times
0
-
[How to handle dialogs following the MVVM design pattern](https://stackoverflow.com/a/75040003/3141792) – BionicCode Jan 19 '23 at 09:27
2 Answers
1
I would like to suggest a solution that is MVVM oriented. One way to judge if we have an MVVM solution is if we can plan a unit test. In this regard we would like to build a view model that is not attempting to raise a dialog and is just setting properties. I use a Popup that we bind to the view model.
The view model will look as following:
public class MainViewModel:Binding
{
bool _isQuestionRaised;
public bool IsQuestionRaised
{
get { return _isQuestionRaised; }
set { _isQuestionRaised = value; NotifyPropertyChanged(nameof(IsQuestionRaised)); }
}
bool _yes;
public bool Yes
{
get { return _yes; }
set {
_yes = value;
NotifyPropertyChanged(nameof(Yes));
if (_yes) DoYesThings();
}
}
bool _no;
public bool No
{
get { return _no; }
set {
_no = value;
NotifyPropertyChanged(nameof(No));
if (_no) DoNoThings();
}
}
public void DoYesThings()
{
IsQuestionRaised = false;
}
public void DoNoThings()
{
IsQuestionRaised = false;
}
public void QuestionIsRaised()
{
IsQuestionRaised = true;
}
public void QuestionIsDismissed()
{
IsQuestionRaised = false;
}
}
The XAML code :
<Grid>
<Grid.Resources>
<Style x:Key="btnStyle" TargetType="Button">
<Setter Property="Height" Value="20"/>
<Setter Property="Width" Value="40"/>
<Setter Property="Margin" Value="10,10,10,10"/>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Click="Button_Click">Raise A Question</Button>
<Popup IsOpen="{Binding IsQuestionRaised}" Width="300" Height="100" Placement="Center" >
<Border BorderThickness="3">
<StackPanel Background="Aqua" Orientation="Vertical">
<TextBlock Margin="20,0,0,20">Yes or No ?</TextBlock>
<StackPanel Orientation="Horizontal">
<Button Click="Button_Click_Yes" Style="{StaticResource btnStyle}">Yes</Button>
<Button Click="Button_Click_No" Style="{StaticResource btnStyle}">No</Button>
<Button Click="Button_Click_Close" Style="{StaticResource btnStyle}">Close</Button>
</StackPanel>
</StackPanel>
</Border>
</Popup>
</Grid>
I use here code behind but we can definitely use delegate command in the ViewModel instead.
public partial class MainWindow : Window
{
MainViewModel _mainViewModel = new MainViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = _mainViewModel;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_mainViewModel.QuestionIsRaised();
}
private void Button_Click_Yes(object sender, RoutedEventArgs e)
{
_mainViewModel.Yes = true;
}
private void Button_Click_No(object sender, RoutedEventArgs e)
{
_mainViewModel.No = true;
}
private void Button_Click_Close(object sender, RoutedEventArgs e)
{
_mainViewModel.QuestionIsDismissed();
}
}

Gilad Waisel
- 120
- 4
0
I would recommend you to make a Window with its own Viewmodel and View.
Like this:
Add a new Window.
DialogWindow.xaml
<Window x:Class="ComboBoxItemPanel_Testing.Dialog_Window"
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:ComboBoxItemPanel_Testing"
mc:Ignorable="d"
Title="Dialog_Window" Height="150" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock Text="Give me a number!"/>
<TextBox Text="{Binding Path=MyNumber}"/>
</StackPanel>
<StackPanel Orientation="Horizontal"
Grid.Row="1"
HorizontalAlignment="Center">
<Button Content="Yes"
Click="Yes_Button"
Margin="10"/>
<Button Content="No"
Margin="10"
Click="No_Button"/>
</StackPanel>
</Grid>
DialogWinodw.xaml.cs
using System.Windows;
namespace ComboBoxItemPanel_Testing
{
/// <summary>
/// Interaction logic for Dialog_Window.xaml
/// </summary>
public partial class Dialog_Window : Window
{
public Dialog_Window(object datacontext)
{
InitializeComponent();
DataContext = datacontext;
}
private void Yes_Button(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
private void No_Button(object sender, RoutedEventArgs e)
{
DialogResult = false;
}
}
}
Add a new class to define your ViewModel. DialogWindowViewModel.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ComboBoxItemPanel_Testing
{
public class DialogWindowViewModel : INotifyPropertyChanged
{
private int _myNumber;
public int MyNumber
{
get => _myNumber;
set
{
if (_myNumber != value)
{
_myNumber = value;
}
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
try
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
catch (Exception ex)
{
Console.WriteLine($"PropertyChanged event handler FAILED : {ex.Message}");
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
And u can use this like this:
DialogWindowViewModel vm = new DialogWindowViewModel();
Dialog_Window dialog = new Dialog_Window(vm);
if (dialog.ShowDialog().Value)
{
//Clicked Yes button
//use ur viewModel
Console.WriteLine("Selected number: " + vm.MyNumber);
}
else
{
//Clicked No Button
Console.WriteLine("You didnt selected a number!");
}

bazsisz
- 394
- 2
- 11
-
Thank you for very clear answer. It is rare to see such detailed answers nowadays. I will try ur suggestion as soon as possible. – Kaan Çağhan Jan 19 '23 at 08:51
-
1Personally, I would suggest you have one window in your app and datatemplate that out into whatever UI you need. For everything. Put UI in usercontrols. Since this question seems to have been asked a couple of times now I've explained this approach in more detail in the question linked in bioniccode's comment. https://stackoverflow.com/questions/75029063/how-to-handle-dialogs-following-the-mvvm-design-pattern/75040003#75040003 – Andy Jan 19 '23 at 11:10