Click here to Skip to main content
15,894,249 members
Articles / Web Development / HTML

Showing Dialogs When Using the MVVM Pattern in WPF or UWP

Rate me:
Please Sign up or sign in to vote.
4.84/5 (77 votes)
25 Jun 2015Apache8 min read 896.8K   233   222
A framework to solve the problem of opening dialogs from a view model when using the MVVM pattern in WPF or UWP.

Image 1

Contents

Introduction

This article will address one of the problems you might run into when using the MVVM pattern, namely opening dialogs from view models. Basic knowledge of the pattern is expected. Josh Smith has written a fantastic article in MSDN Magazine which can serve as the starting point for those that are unfamiliar with the pattern.

There already exists numerous MVVM frameworks, and for those looking for a more complete solution to MVVM I would recommend taking a look at the following frameworks:

This framework is not a complete all-inclusive MVVM framework. It is designed to simplify the concept of opening dialogs from a view model when using MVVM in WPF or UWP. It does a pretty good job of that but nothing else. It doesn't contain any fancy view model base classes, nor any event broker or service locator. The only extra benefit you'll get is the ability to easily write unit tests for your view models in the same manner unit tests are written for other classes. That you will get.

The framework has built in support for opening the following dialogs:

  • Modal dialogs
  • Non-modal dialogs
  • Message boxes
  • Open file dialogs
  • Save file dialogs
  • Folder browser dialogs

WPF usage

More interesting than the implementation of the framework is the usage of it, so lets start with that. This chapter will demonstrate the code required to show the supported WPF dialogs.

Showing a dialog

A dialog can be shown either as modal or non-modal. A modal dialog halts code execution and awaits the dialog result while a non-modal dialog continues code execution without waiting for any dialog result. Showing a dialog can be performed in either of two ways, either by explicit specifying the dialog type or by implicit using the dialog type locator. Both concepts and the difference in usage is described in the upcoming chapters.

Explicit dialog type syntax

The most straight forward syntax to use is the explicit syntax where the generic methods IDialogService.ShowDialog<T> and IDialogService.Show<T> shows a modal respectively non-modal dialog of the type T. The MVVM purists among the readers are most certainly appalled by the fact that the view type is defined in the view model. For them there is the implicit syntax and the dialog type locator.

Implicit dialog type syntax and the dialog type locator

Specifying a dialog type in a view model might either be unwanted or impossible in certain situations, thus the framework supports opening a dialog without specifying the dialog type. IDialogService.ShowDialog and IDialogService.Show are the non-generic methods where the dialog type isn't specified in the method call. However, IDialogService still has to know the dialog type in order to create and open the dialog. This is where the concept of a dialog type locator comes into play.

A dialog type locator is a function of type Func<INotifyPropertyChanged, Type> capable of resolving a dialog type based on a specified view model. The implementation of DialogService comes with a default dialog type locator that uses a common naming convention used in a multitude of articles and code samples regarding the MVVM pattern. The convention states that if the name of the view model is MyNamespace.ViewModels.MyDialogViewModel then the name of the dialog is MyNamespace.Views.MyDialog. If this convention doesn't fit your code structure the default locator can be overridden by specifying your own implementation in the constructor of DialogService.

Showing a modal dialog using explicit dialog type syntax

To show a modal dialog using explicit dialog type syntax start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.Dialog.Modal.Views.ModalDialogTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">
  
</UserControl>

In the view model, open the dialog by calling IDialogService.ShowDialog<T>.

public class ModalDialogTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public ModalDialogTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void ShowDialog()
  {
    var dialogViewModel = new AddTextDialogViewModel();

    bool? success = dialogService.ShowDialog<AddTextDialog>(this, dialogViewModel));
    if (success == true)
    {
      Texts.Add(dialogViewModel.Text);
    }
  }
}

Showing a modal dialog using implicit dialog type syntax

To show a modal dialog using implicit dialog type syntax start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.Dialog.Modal.Views.ModalDialogTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">
  
</UserControl>

Make sure the dialog type locator can locate the dialog type, and then let the view model open the dialog by calling IDialogService.ShowDialog.

public class ModalDialogTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public ModalDialogTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void ShowDialog()
  {
    var dialogViewModel = new AddTextDialogViewModel();

    bool? success = dialogService.ShowDialog(this, dialogViewModel));
    if (success == true)
    {
      Texts.Add(dialogViewModel.Text);
    }
  }
}

Showing a non-modal dialog using explicit dialog type syntax

To show a non-modal dialog using explicit dialog type syntax start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.Dialog.NonModal.Views.NonModalDialogTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">
  
</UserControl>

In the view model, open the dialog by calling IDialogService.Show<T>.

public class NonModalDialogTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public NonModalDialogTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void Show()
  {
    var dialogViewModel = new CurrentTimeDialogViewModel();
    dialogService.Show<CurrentTimeDialog>(this, dialogViewModel));
  }
}

Showing a non-modal dialog using implicit dialog type syntax

To show a non-modal dialog using implicit dialog type syntax start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.Dialog.NonModal.Views.NonModalDialogTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">
  
</UserControl>

Make sure the dialog type locator can locate the dialog type, and then let the view model open the dialog by calling IDialogService.Show.

public class NonModalDialogTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public NonModalDialogTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void Show()
  {
    var dialogViewModel = new CurrentTimeDialogViewModel();
    dialogService.Show(this, dialogViewModel));
  }
}

Showing a message box

To show a message box start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.MessageBox.Views.MessageBoxTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">

</UserControl>

In the view model, open the dialog by calling IDialogService.ShowMessageBox.

public class MessageBoxTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public MessageBoxTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void ShowMessageBox()
  {
    dialogService.ShowMessageBox(
      this,
      "This is the text.",
      "This Is The Caption",
      MessageBoxButton.OKCancel,
      MessageBoxImage.Information);
  }
}

Showing an open file dialog

To show an open file dialog start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.OpenFileDialog.Views.OpenFileTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">
  
</UserControl>

In the view model, open the dialog by calling IDialogService.ShowOpenFileDialog.

public class OpenFileTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public OpenFileTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void OpenFile()
  {
    var settings = new OpenFileDialogSettings
    {
      Title = "This Is The Title",
      InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
      Filter = "Text Documents (*.txt)|*.txt|All Files (*.*)|*.*"
    };

    bool? success = dialogService.ShowOpenFileDialog(this, settings);
    if (success == true)
    {
      Path = settings.FileName;
    }
  }

Showing a save file dialog

To show a save file dialog start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.SaveFileDialog.Views.SaveFileTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">
    
</UserControl>

In the view model, open the dialog by calling IDialogService.ShowSaveFileDialog.

public class SaveFileTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public SaveFileTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void SaveFile()
  {
    var settings = new SaveFileDialogSettings
    {
      Title = "This Is The Title",
      InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
      Filter = "Text Documents (*.txt)|*.txt|All Files (*.*)|*.*",
      CheckFileExists = false
    };

    bool? success = dialogService.ShowSaveFileDialog(this, settings);
    if (success == true)
    {
      Path = settings.FileName;
    }
  }
}

Showing a folder browser dialog

To show a folder browser dialog start by registering the view by decorating the XAML with the attached property DialogServiceViews.IsRegistered.

<UserControl
  x:Class="DemoApplication.Features.FolderBrowserDialog.Views.FolderBrowserTabContent"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
  md:DialogServiceViews.IsRegistered="True">
  
</UserControl>

In the view model, open the dialog by calling IDialogService.ShowFolderBrowserDialog.

public class FolderBrowserTabContentViewModel : INotifyPropertyChanged
{
  private readonly IDialogService dialogService;
  
  public FolderBrowserTabContentViewModel(IDialogService dialogService)
  {
    this.dialogService = dialogService;
  }
  
  private void BrowseFolder()
  {
    var settings = new FolderBrowserDialogSettings
    {
      Description = "This is a description"
    };

    bool? success = dialogService.ShowFolderBrowserDialog(this, settings);
    if (success == true)
    {
      Path = settings.SelectedPath;
    }
  }
}

UWP usage

It is pretty mindboggling that this framework can be run UWP, in other words a Raspberry PI or any other device that supports Windows 10 IoT. This chapter will demonstrate the code required to show the supported UWP dialogs.

Showing a content dialog

Showing a content dialog can be performed in either of two ways, either by explicit specifying the dialog type or by implicit using the dialog type locator. Both concepts and the difference in usage is described below.

Explicit dialog type syntax

The most straight forward syntax to use is the explicit syntax where the generic methodShowContentDialogAsync<T> shows a content dialog of the type T. The MVVM purists are most certainly appalled by the fact that the view type is defined in the view model. For them there is the implicit syntax and the dialog type locator.

Implicit dialog type syntax and the dialog type locator

Specifying a dialog type in a view model might either be unwanted or impossible in certain situations, thus the framework supports opening a content dialog without specifying the dialog type. IDialogService.ShowContentDialogAsync is the non-generic method where the dialog type isn't specified in the method call. However, IDialogService still has to know the dialog type in order to create and open the dialog. This is where the concept of a dialog type locator comes into play.

A dialog type locator is a function of type Func<INotifyPropertyChanged, Type> capable of resolving a dialog type based on a specified view model. The implementation of DialogServicecomes with a default dialog type locator that uses a common naming convention used in a multitude of articles and code samples regarding the MVVM pattern. The convention states that if the name of the view model is MyNamespace.ViewModels.MyDialogViewModel then the name of the content dialog is MyNamespace.Views.MyDialog. If this convention doesn't fit your code structure the default locator can be overridden by specifying your own implementation in the constructor ofDialogService.

Showing a content dialog using explicit dialog type syntax

To show a content dialog using explicit dialog type syntax callIDialogService.ShowContentDialogAsync<T> from the view model.

public class MainPageViewModel : INotifyPropertyChanged
{
    private readonly IDialogService dialogService;

    public MainPageViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;
    }

    private async void ShowContentDialog()
    {
        var viewModel = new AddTextContentDialogViewModel();

        ContentDialogResult result = await dialogService.ShowContentDialogAsync<AddTextContentDialog>(viewModel)
        if (result == ContentDialogResult.Primary)
        {
            Texts.Add(dialogViewModel.Text);
        }
    }
}

Showing a content dialog using implicit dialog type syntax

To show a content dialog using implicit dialog type syntax callIDialogService.ShowContentDialogAsync from the view model.

public class MainPageViewModel : INotifyPropertyChanged
{
    private readonly IDialogService dialogService;

    public MainPageViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;
    }

    private async void ShowContentDialog()
    {
        var viewModel = new AddTextContentDialogViewModel();

        ContentDialogResult result = await dialogService.ShowContentDialogAsync(viewModel)
        if (result == ContentDialogResult.Primary)
        {
            Texts.Add(dialogViewModel.Text);
        }
    }
}

Showing a message dialog

In the view model, open the dialog by calling IDialogService.ShowMessageDialogAsync.

public class MainPageViewModel : INotifyPropertyChanged
{
    private readonly IDialogService dialogService;

    public MainPageViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;
    }

    private async void ShowMessageDialog()
    {
        await dialogService.ShowMessageDialogAsync(
            "This is the text.",
            "This Is The Title",
            new[]
            {
                new UICommand { Label = "OK" },
                new UICommand { Label = "Close" }
            });
    }
}

Showing single and multiple file pickers

Pick single file

In the view model, open the dialog by calling IDialogService.PickSingleFileAsync.

public class MainPageViewModel : ViewModelBase
{
    private readonly IDialogService dialogService;

    public MainPageViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;
    }

    private async void PickSingleFile()
    {
        var settings = new FileOpenPickerSettings
        {
            SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
            FileTypeFilter = new List<string> { ".txt" }
        };

        StorageFile storageFile = await dialogService.PickSingleFileAsync(settings);
        if (storageFile != null)
        {
            SingleFilePath = storageFile.Path;
        }
    }
}

Pick multiple files

In the view model, open the dialog by calling IDialogService.PickMultipleFilesAsync.

public class MainPageViewModel : ViewModelBase
{
    private readonly IDialogService dialogService;

    public MainPageViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;
    }

    private async void PickMultipleFiles()
    {
        var settings = new FileOpenPickerSettings
        {
            SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
            FileTypeFilter = new List<string> { ".txt" }
        };

        IReadOnlyList<StorageFile> storageFiles = await dialogService.PickMultipleFilesAsync(settings);
        if (storageFiles.Any())
        {
            MultipleFilesPath = string.Join(";", storageFiles.Select(storageFile => storageFile.Path));
        }
    }
}

Showing a save file picker

In the view model, open the dialog by calling IDialogService.PickSaveFileAsync.

public class MainPageViewModel : INotifyPropertyChanged
{
    private readonly IDialogService dialogService;

    public MainPageViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;
    }

    private async void SaveFile()
    {
        var settings = new FileSavePickerSettings
        {
            SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
            FileTypeChoices = new Dictionary<string, IList<string>>
            {
              { "Text Documents", new List<string> { ".txt" } }
            },
            DefaultFileExtension = ".txt"
        };

        StorageFile storageFile = await dialogService.PickSaveFileAsync(settings);
        if (storageFile != null)
        {
            Path = storageFile.Path;
        }
    }
}

Showing a single folder picker

In the view model, open the dialog by calling IDialogService.PickSingleFolderAsync.

public class MainPageViewModel : ViewModelBase
{
    private readonly IDialogService dialogService;

    public MainPageViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;
    }

    private async void BrowseFolder()
    {
        var settings = new FolderPickerSettings
        {
            SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
            FileTypeFilter = new List<string> { ".txt" }
        };

        StorageFolder storageFolder = await dialogService.PickSingleFolderAsync(settings);
        if (storageFolder != null)
        {
            Path = storageFolder.Path;
        }
    }
}

GitHub

The code is also available on GitHub. You are welcome to create issues and pull requests.

NuGet

If you want to include MVVM Dialogs in your project, you can install it directly from NuGet.

To install MVVM Dialogs, run the following command in the Package Manager Console:

PM> Install-Package MvvmDialogs

History

  • 21 September 2016: Code update
    • Updated the constructors of DialogService, making the class more friendly to IoC containers
  • 22 May 2016: Code update
    • Added support for Universal Windows Platform (UWP)
  • 26 August 2015: Article update.
    • Added information about integration with MVVM Light after comments by flyingxu.
  • 24 June 2015: Major code refactoring.
    • Source available on GitHub.
    • Package available as NuGet.
  • 5 October 2010: Code update.
    • Updated source according to comments by d302241.
  • 4 April 2010: Code update.
    • Updated source according to comments by Michael Sync.
    • Converted to .NET 4.
  • 18 June 2009: Code update.
    • Code no longer throws exception in Designer mode.
    • Fixed wrong interface summary.
  • 2 June 2009: Code update.
    • Added the ShowOpenFileDialog method to IDialogService.
    • Implemented a service locator instead of keeping DialogService as a Singleton.
  • 27 May 2009: Article update.
    • Updated introduction after comments from William E. Kempf.
  • 25 May 2009: Initial version.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
Software Developer Axis Communications
Sweden Sweden
Got my first computer in the 90's and loved it even though it sounded like a coffeemaker.

Now getting paid for designing cool applications, and drinks the coffee instead of listening to it being made.

Comments and Discussions

 
GeneralRe: Problem with Test ShowInformationTest Pin
Michael Bookatz14-Jun-11 13:01
Michael Bookatz14-Jun-11 13:01 
GeneralRe: Problem with Test ShowInformationTest Pin
FantasticFiasco14-Jun-11 18:53
FantasticFiasco14-Jun-11 18:53 
GeneralThe coupling of DialogService with the rest of the project Pin
mackius25-Apr-11 3:33
mackius25-Apr-11 3:33 
GeneralRe: The coupling of DialogService with the rest of the project Pin
FantasticFiasco25-Apr-11 5:05
FantasticFiasco25-Apr-11 5:05 
GeneralRe: The coupling of DialogService with the rest of the project Pin
mackius25-Apr-11 7:30
mackius25-Apr-11 7:30 
GeneralRe: The coupling of DialogService with the rest of the project Pin
FantasticFiasco25-Apr-11 9:13
FantasticFiasco25-Apr-11 9:13 
GeneralInteresting Pin
BFullwood9-Feb-11 15:01
BFullwood9-Feb-11 15:01 
GeneralRe: Interesting Pin
FantasticFiasco10-Feb-11 3:42
FantasticFiasco10-Feb-11 3:42 
Nice you've come around to WPF, WinForms is so yesterday Wink | ;)

Lets start answering your questions...
BFullwood wrote:
I also see that if you want to create any new type of dialog, you have to create at least two additional classes for each . . . all to avoid a single, very simple call in a ViewModel class that throws up a View. Sure, that violates an important principle, namely, separation of concerns. However . . . can anyone say, "over-engineered?"

I am not quite following you here when you are referring to "two additional classes for each". I guess you don't mean the view (e.g. PersonDialog.xaml) or the code-behind of the view (e.g. PersonDialog.xaml.cs). Other than those there is only the DialogService and the actual viewmodel (e.g. PersonDialogViewModel.cs) left. Of those two I can subtract the viewmodel since it is a part of the MVVM pattern, and that leaves the dialog service. As a result I would say: "Apart from the classes defined by MVVM, namely the view and the viewmodel, this framework requires you to use one extra class, namely the DialogService.

I know that taking the shortcut of opening a view from the viewmodel seems tempting, but I would say don't. Not primarily based on the separation of concerns, but based on testability. According to me testability is the primary reason why you should use MVVM. Does testability come with a cost? Well that depends on your notion of cost. If it only includes the time a developer is spending on a project it is cheaper to skip testability, but if your cost also include the possible bug reports/fixes the developer has to attend I would say it is cheaper to develop testable code.

Opening a modal dialog from a viewmodel is not testable, but if you don't open the dialog yourself but lets a third-party do it, say the dialog service, you can mock that third party in a test and the viewmodel code becomes testable. Hurray!

BFullwood wrote:
1. Why do you concern yourself with one ViewModel not being tightly coupled to other ViewModels? I'm having a tough time seeing why you wouldn't create ViewModels as Singletons and then freely and easily call one ViewModel from another ViewModel. Sure, tight connections might require that you upon occasion modify two ViewModels instead of one, but is that worse than bending yourself into a pretzel to ensure that you don't?

It seems like a mantra but the answer is again testability. Lets say viewmodel A is tightly coupled with viewmodel B, and viewmodel B is tightly coupled with viewmodel C and D. In testing viewmodel A, you would be forced to set up viewmodel B, C and D. That's a LOT of work for testing one viewmodel.

Having the viewmodels as Singletons is not good either, are you sure that two instances of the same viewmodel shouldn't be allowed to coexist? Lets say you have an application that can show stock indexes. By clicking on a stock you can see extended information about the stock. With singletons you could only be watching one stock at the time, but what if the requirements of the application would force you to show two indexes in separate windows at the same time? That wouldn't be impossible using singletons.

Have a look at the event aggregator in Prism, it is an implementation of the Mediator pattern, where the sender and receiver has no notion of each other when it comes to sending events.

BFullwood wrote:
2. Instead of doing all this, I suppose you could create an instance of every possible dialog and have it siting in memory. You then control their visibility with properties. You reduce complexity, but you could kill memory, depending upon how many Views/Dialogs you have in your app. Thoughts?

I am not sure you reduce complexity, because based on my previous answers I think having everything tightly coupled is a bad thing. If things weren't coupled you would need somebody managing the visibility of the dialogs, and we are back to the same complexity again.

BFullwood wrote:
3. Strictly speaking, MVVM is violated right off the bat when you start the app. App.xaml.cs has to create at least the first ViewModel and the first View. All in one spot. The horror!

I can see that for someone just starting with WPF and MVVM that there seems to be no way round this, but there is. A very simple and MVVM friendly way. Lets start with App.xaml.cs. Remove the view and viewmodel:

public partial class App : Application
{
  protected override void OnStartup(StartupEventArgs e)
  {
    base.OnStartup(e);

    // Configure service locator
    ServiceLocator.RegisterSingleton<IDialogService, DialogService>();
    ServiceLocator.RegisterSingleton<IPersonService, PersonService>();
    ServiceLocator.RegisterSingleton<IWindowViewModelMappings, WindowViewModelMappings>();
    ServiceLocator.Register<IOpenFileDialog, OpenFileDialogViewModel>();
  }
}


The we're moving on to App.xaml:
<Application
  x:Class="MVVM_Dialogs.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  StartupUri="View\MainWindow.xaml"/>


Here we are specifying that MainWindow.xaml should be the startup URI. Finally we move on to MainWindow.xaml.
<Window
  x:Class="MVVM_Dialogs.View.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:ViewModel="clr-namespace:MVVM_Dialogs.ViewModel"
  xmlns:Service="clr-namespace:MVVM_Dialogs.Service"
  Title="MVVM Dialog Example"
  WindowStartupLocation="CenterScreen"
  Service:DialogService.IsRegisteredView="True"
  Height="300"
  Width="400">
	
  <Window.DataContext>
    <ViewModel:MainWindowViewModel />
  </Window.DataContext>

...


We define a ViewModel prefix and instantiate the viewmodel here. All according to any guidance defined by WPF and MVVM.

What can you learn from this? Well, don't jump to conclusions before you understand the bigger picture.

As a finale, you ask why my approach is superior. I would ask, superior to what? The .NET framework itself does not help you when it comes to opening dialogs from a viewmodel. There exists other frameworks handling a hole lot more than dialogs, like Cinch, Caliburn and Onyx. If you think my approach is complex, take a look at those Smile | :) I think my approach is simple, easy to understand and very straight forward. But that's just me...

Happy coding.
GeneralRe: Interesting Pin
BFullwood11-Feb-11 3:42
BFullwood11-Feb-11 3:42 
GeneralBug + Solution: Showing generic dialog with Type Targeted DataTemplate Content Pin
Andre Luus26-May-10 23:29
Andre Luus26-May-10 23:29 
GeneralRe: Bug + Solution: Showing generic dialog with Type Targeted DataTemplate Content Pin
FantasticFiasco27-May-10 4:10
FantasticFiasco27-May-10 4:10 
GeneralClosing a dialog Pin
ldyc22-Apr-10 2:19
ldyc22-Apr-10 2:19 
GeneralRe: Closing a dialog Pin
FantasticFiasco22-Apr-10 2:49
FantasticFiasco22-Apr-10 2:49 
GeneralRe: Closing a dialog Pin
Flobby28-May-12 21:38
Flobby28-May-12 21:38 
GeneralRe: Closing a dialog Pin
FantasticFiasco29-May-12 7:31
FantasticFiasco29-May-12 7:31 
QuestionIs there a VS2008 version? Pin
ldyc12-Apr-10 8:19
ldyc12-Apr-10 8:19 
AnswerRe: Is there a VS2008 version? Pin
FantasticFiasco12-Apr-10 20:48
FantasticFiasco12-Apr-10 20:48 
GeneralRe: Is there a VS2008 version? Pin
ldyc13-Apr-10 1:50
ldyc13-Apr-10 1:50 
GeneralRe: Is there a VS2008 version? Pin
FantasticFiasco13-Apr-10 4:03
FantasticFiasco13-Apr-10 4:03 
GeneralRe: Is there a VS2008 version? Pin
ldyc13-Apr-10 12:22
ldyc13-Apr-10 12:22 
GeneralRe: Is there a VS2008 version? Pin
FantasticFiasco16-Apr-10 2:12
FantasticFiasco16-Apr-10 2:12 
GeneralRe: Is there a VS2008 version? Pin
ldyc19-Apr-10 2:34
ldyc19-Apr-10 2:34 
GeneralRe: Is there a VS2008 version? Pin
FantasticFiasco19-Apr-10 4:40
FantasticFiasco19-Apr-10 4:40 
GeneralRe: Is there a VS2008 version? Pin
ldyc19-Apr-10 7:06
ldyc19-Apr-10 7:06 
GeneralRe: Is there a VS2008 version? [modified] Pin
FantasticFiasco19-Apr-10 19:52
FantasticFiasco19-Apr-10 19:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.