2

I delegate creation(showing) of my Windows to my WindowFactory, that attaches a ViewModel to the View and shows the window. It is injected into my MainViewModel Constructor parameters.

The factory itself is very simple:

public class ProductionWindowFactory : IWindowFactory
{
    public void CreateNewWindow()
    {
        PhoneWindow window = new PhoneWindow();
        {
            window.DataContext = new phoneWindowViewModel();
        }
        window.Show();
    }
}

Now, I'm aiming at implementing more functionality of my new windows, that will happen on certain button clicks IN that new window.

As I am fairly new to Factories in general, I'm struggling to grasp a certain concept:

Example:

We have a ViewA that has a ViewModelA attached to it. That view has a button with a command attached, that tells our WindowFactory to show a new ViewB.

ViewB has a ViewModelB and a close button, that tells it to close ViewB.

Now, since we shouldn't reference our ViewB in our ViewModelB, we have to somehow let it know which view it should close.

I have come up with possible ideas / solutions, but I would really appreciate you letting me know which one follows the MVVM and Factory pattern "the most", and which one is usually used in such situations.

  1. Make our ViewModelB take an instance of windowFactory that created ViewB as a parameter on initialization, and build a method in the Factory that closes ViewB and is executed through button click -> command.
  2. Create an IWindowManager? that inherits from IWindowFactory and build a WindowManager class, that extends the capabilities of our WindowFactory, and push it in ViewModel constructors as described above.
  3. Any other correct solution, that I am completely unaware of?

Please bear in mind, that the above is just an example. Ideally, I'd like to implement more of advanced functionality to my windows, and have an ability to create & manage multiple different ones using that one factory.

I have not attached much code, since I'm still at the stage of learning and deciding which solution should I go with.

EDIT - REGARDING POSSIBLE DUPLICATE:

My question differs from the proposed duplicate, as the other one is simply about managing of closing windows - My question is about doing that as well, but following a FactoryPattern.

I have specified very clear guidelines in what I am trying to achieve and in what ways, that are completely different from the question linked.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Kamil Solecki
  • 1,106
  • 20
  • 34
  • Possible duplicate of [MVVM: Is code-behind evil or just pragmatic?](http://stackoverflow.com/questions/40257513/mvvm-is-code-behind-evil-or-just-pragmatic) – Haukinger Dec 05 '16 at 09:43
  • I wouldn't say its a duplicate, since my question is strictly about the factory pattern. The question you linked is not, its just about closing windows. – Kamil Solecki Dec 05 '16 at 09:46
  • "we have to somehow let it know which view it should close" if that isn't the question, can you try to be a bit more precise in what exactly is your question? – Haukinger Dec 05 '16 at 10:16
  • I have pushed the actual question to blockquote. Also, the 3 points below it are a part of it as well. – Kamil Solecki Dec 05 '16 at 10:18

2 Answers2

2

First of all, the answer is none. The job of a factory is to create new objects, think of it as an elaborate new operator. Also, the idea of following a pattern "the most" is problematic in and of itself. You employ patterns because they help you achieve certain goals, e.g. you employ mvvm to evade coded-ui tests as much as possible, because they are fragile, normally.

That being said, what to do with its view is completely up to the view's view model.

Example: if one view model needs to close its own window, do it with a command as illustrated in the comment. If a view has a close all-button, its view model will have a dependency on some kind of window registry that can enumerate all open windows for the close all-command to close.

When looking at your view model, try to come up with an idea of what services it needs from the rest of the application, and inject those dependencies as interfaces. When implementing the interfaces, most likely there will be classes that implement more than one, e.g. WindowManager might implement IWindowFactory and IWindowRegistry thus making it very easy to put all newly created windows into the list of open windows. The window will have a dependency on the IWindowRegistry, too, most likely, to unregister itself when it gets closed.

Haukinger
  • 10,420
  • 2
  • 15
  • 28
1

The duplicate was not far off. Here is a simple adaptation of the scenario in OP

interface IView {
    void Close();
}

class ViewAdapter : IView {
    readonly Window view;
    public ViewAdapter(Window view){
        this.view = view;
    }

    public void Close() {
        view.Close();
    }
}

public class ProductionWindowFactory : IWindowFactory {
    public void CreateNewWindow() {
        var view = new PhoneWindow();
        var viewAdapter = new ViewAdapter(view)
        var viewModel = new phoneWindowViewModel(viewAdapter);

        //Bind
        view.DataContext = viewModel;

        view.Show();
    }
}

If the view model wants to instruct that the view be closed it can ask the injected contract to do so.

Nkosi
  • 235,767
  • 35
  • 427
  • 472