user2430797
user2430797

Reputation: 330

WPF MVVM - how to inject a service into the ViewModel

I'm fairly new to WPF and MVVM and I need to create a simple dialog feature that allows me to popup a confirmation message on the screen such as "Confirm delete?" with y/n buttons. I created a dialog service for this (which in essence is a simple wrapper around the System.Windows.MessageBox) and I'd like to use it throughout my application. As I understand, I should inject this service via the constructor of all my ViewModels like this:

public MainWindowViewModel(IDialogService injectedDialogService) // Dialog service dependency injection
{
    dialogService = injectedDialogService;
    ...
    ...
}

I declared dialogService in the respective ViewModel as:

 private IDialogService dialogService;

And then I was hoping to use it throughout the ViewModel like this:

dialogService.ShowDialog("Some message...");

Or, like this:

if (dialogService.ShowDialog("Confirm delete?", "Confirmation",  DialogButtons.YesNo) == DialogResult.Yes)
{
    // Delete it...
}

However, I get the following complaint from the respective View:

The type "MainWindowViewModel" does not include any accessible constructors.

And the following error message from the View when I compile the solution:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

This is how I correlate the View with the ViewModel:

<Window.Resources>
        <vm:MainWindowViewModel x:Key="MainWindowViewModel"/>
        ...
        ...
        ...
</Window.Resources>

And the data context:

<Window.DataContext>
        <vm:MainWindowViewModel/>
</Window.DataContext>

In case this helps, here is my dialog service:

namespace FIM.Framework.Services
{
    public enum DialogButtons
    {
        OK = 0,
        OKCancel = 1,
        YesNoCancel = 3,
        YesNo = 4,
    }

    public enum DialogResult
    {
        None = 0,
        OK = 1,
        Cancel = 2,
        Yes = 6,
        No = 7,
    }

    public enum DialogImage
    {
        None = 0,
        Error = 16,
        Hand = 16,
        Stop = 16,
        Question = 32,
        Exclamation = 48,
        Warning = 48,
        Information = 64,
        Asterisk = 64,
    }

    public interface IDialogService
    {
        DialogResult ShowDialog(string messageBoxText, 
                                        string caption = null,
                                        DialogButtons buttons = DialogButtons.OK,
                                        DialogImage icon = DialogImage.None,
                                        DialogResult defaultResult = DialogResult.None);
    }

    public class DialogService : IDialogService
    {
        public DialogResult ShowDialog(string messageBoxText, 
                                       string caption = null, 
                                       DialogButtons buttons = DialogButtons.OK, 
                                       DialogImage image = DialogImage.None, 
                                       DialogResult defaultResult = DialogResult.None)
        {
            return (DialogResult)System.Windows.MessageBox.Show(messageBoxText, 
                                                                caption,
                                                                (System.Windows.MessageBoxButton)buttons,
                                                                (System.Windows.MessageBoxImage)image,
                                                                (System.Windows.MessageBoxResult)defaultResult);
        }
     }
}

Can you please help me with this problem? If my approach is wrong, or not the best, could someone please suggest a better implementation for a dialog service? Many thanks.

Upvotes: 1

Views: 2600

Answers (1)

Kostas K.
Kostas K.

Reputation: 8518

Since your MainWindowViewModel is expecting a parameter, you cannot instantiate it in xaml. You need to override the OnStartup() in the code-behind of your App.xaml file.


  1. In App.xaml remove the StartupUri="MainWindow.xaml".
  2. In the code-behind of the App.xaml, override the OnStartup(StartupEventArgs e):

protected override void OnStartup(StartupEventArgs e)
{
     base.OnStartup(e);

     var viewmodel = new MainWindowViewModel(new DialogService());
     var window = new MainWindow { DataContext = viewmodel };
     window.Show();
 }

Upvotes: 3

Related Questions