4

I have created a custom messageBox Window to replace the typical MessageBox.

My custom messageBox (child Window) needs parent window to be passed as an argument. The parent window is where child window will be located within in the location specified (Top Left, Top Center, etc.) also as an argument.

So when calling my custom messageBox from view model, I need to get the Window to pass it through. How can I get the Window associated to the view model?

Maybe using an Interface like commented here? I am trying to implement it but this.DataContext.View does not exist.

I am using Visual Studio 2008.

ATTEMPT #1: mm8 solution

<Window x:Class="MyNamespace.Main"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewmodel="clr-namespace:MyNamespace.ViewModels">
    <Window.Resources>
        <viewmodel:MainViewModel x:Key="wMainViewModel" />
    </Window.Resources>

    <Grid DataContext="{StaticResource wMainViewModel}">
    </Grid>
</Window>

Taken into account that I initialize DataContext from xaml and not in code-behind from constructor, how can I pass the view to the view model¿?

Willy
  • 9,848
  • 22
  • 141
  • 284
  • 3
    isn't code that handles messageboxes etc. the *other* part of MVVM? (as in ; it has no business in your model) – Timothy Groote Nov 13 '17 at 14:07
  • 2
    Either you pass it to the ViewModel or use `Application.Current.MainWindow`. But yeah, as Timothy said, your ViewModel has no business knowing about Windows. – Manfred Radlwimmer Nov 13 '17 at 14:08
  • 1
    Possible duplicate of [how to show Messagebox in MVVM](https://stackoverflow.com/questions/3705991/how-to-show-messagebox-in-mvvm) – Sinatr Nov 13 '17 at 14:08
  • @ManfredRadlwimmer using Application.Current.MainWindow is ok when you have only one window but when you have a lot it is not suitable. – Willy Nov 13 '17 at 14:20
  • 2
    @user1624552 Then use `Application.Current.Windows.OfType().FirstOrDefault()` or use MVVM properly :) – Manfred Radlwimmer Nov 13 '17 at 14:23

1 Answers1

8

How can I get the Window associated to the view model?

You could inject the view model with an interface that the window implements:

public interface IView
{
    double Top { get; }
    double Left { get; }
    double Height { get; }
    double Width { get; }
}

public partial class MainWindow : Window, IView
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel(this);
    }
}

public class ViewModel
{
    private readonly IView _view;

    public ViewModel(IView view)
    {
        _view = view;
    }

    //...
}

Then the view model knows only about an interface (which maybe should be called something else than IView).

If you want an ugly and non-MVVM friendly shortcut, you could use the Application class:

var win = Application.Current.MainWindow;

A factory class to create everything:

public MainWindow WindowFactory()
{
    MainWindow mainWindow = new MainWindow();
    ViewModel viewModel = new ViewModel();
    mainWindow.DataContext = viewModel;

    return mainWindow;
}
Ignacio Soler Garcia
  • 21,122
  • 31
  • 128
  • 207
mm8
  • 163,881
  • 10
  • 57
  • 88