Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM show new window from VM when seperated projects

My question involves something where thousand and one topics are created about, and if I overlooked an answer to my question, I'm sorry, but as far as I looked none really could answer my question. For example: Opening new window in MVVM WPF

The answers are okay when if you use just one WPF project (including models, vms and views) but since I'm learning how to implement MVVM the correct way (and I've read multiple times that best practice is to create seperate class lib (dll's) for model, viewmodel and a seperate gui project) that doesn't seem to work in my eyes because if I want to create an interface like IWindowService (described on previous url and also here, It's impossible to access Window or Control class because then I should have a reference to the gui project and the whole goal of the pattern is wrecked.

So my question is how to show a new window (with a new viewmodel) from for example the MainViewModel, while respecting the loosely coupled MVVM principles AND seperate projects.

More in depth example of what I'm trying to achieve:

I have following structure:

MODEL (dll project)
     Profile

VIEWMODEL (dll project)
     MainViewModel
     AddProfileViewModel

VIEW (WPF) (exe project)
     MainWindow
     AddProfileWindow

I open MainWindow and I want to press the button AddProfile, then AddProfileWindow needs to show up with the AddProfileViewModel attached to it.

like image 458
JC97 Avatar asked Nov 17 '17 14:11

JC97


1 Answers

  • Define the IWindowService interface in the model project.
  • Reference the model project from the view model project.
  • Implement the IWindowService in the WPF application (view) project.

The button should then be bound to an ICommand that uses IWindowService to open the window. Something like this:

public class MainWindowViewModel
{
    private readonly IWindowService _windowService;

    public MainWindowViewModel(IWindowService windowService)
    {
        _windowService = windowService;
        AddProfile = new DelegateCommand(() =>
        {
            _windowService.OpenProfileWindow(new AddProfileViewModel());
        });
    }

    public ICommand AddProfile { get; }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel(new WindowService());
    }
}

public class WindowService : IWindowService
{
    public void OpenProfileWindow(AddProfileViewModel vm)
    {
        AddProfileWindow win = new AddProfileWindow();
        win.DataContext = vm;
        win.Show();
    }
}
like image 56
mm8 Avatar answered Nov 07 '22 07:11

mm8