简体   繁体   中英

WPF using simple injector to open new View

How can i open a new View/Window using Simple Injector to inject dependencies?

I can launch the wpf application using the simple injector, the problem is: how can i open a new window/view from my window/view which is already launched

This question is all about design and Simple Injector is just an implementation detail somewhere in the composition root .

I wrote another answer here on stackoverflow to a similar question regarding Windows Forms. The ideas in that answer are not that different for WPF.

There are several possibilities to do this depending on: - How many, other than the main window, windows are needed - Do the other windows also need to navigate to other windows or are other windows only opened from the main window - What is the lifestyle of the windows. It is typically pretty hard to create windows that are truly singleton for the complete lifetime of the application

  1. If the application consists of just a few windows and the window can have a singleton lifestyle, just put the needed windows in the constructor of the main window. If the lifestyle can't be singleton, you could inject a Func<T> factory method per window.
  2. Make the first or main window part of the composition root. Put in the container as a constructor parameter and resolve the other windows directly from the container before showing them. In this case the only and single responsibility of this window must be the opening/showing of the application windows.
  3. Create a INavigationService with an implementation also part of the composition root
  4. Use an MVVM tool like Caliburn Micro and redirect the GetInstance() method in the Caliburn Bootstrapper class directly to the Simple Injector container
  5. Make a complete design change...

Possibilities 1, 2 and 4 are straightforward to implement. The NavigationService in the most simple form is also pretty straightforward and would look something like:

public class NavigationService : INavigationService
{
    private readonly Container container;

    public NavigationService(Container container)
    {
        this.container = container;
    }

    public void ShowView<TView>() where TView : Window 
    {
        var view = this.CreateWindow<TView>();

        view.Show();
    }

    public bool? ShowDialog<TView>() where TView : Window
    {
        var view = this.CreateWindow<TView>();

        return view.ShowDialog();
    }

    private Window CreateWindow<TView>() where TView : Window
    {
        return this.container.GetInstance<TView>();
    }
}

If we would however take another angle on this, we could create a design which in essence an UI version of this design for handling commands and queries . These patterns will really solve your problems, both on the businesslayer side and UI side.

In most LOB applications a screen typically is opened to let the make a choice or selection and another part are screens letting the user enter data and save this to some data store. If we look at this concerns from an abstract level it doesn't really matter that this is handled by a piece of UI to let the user interact. We could just think of it as a service which queries or edits data from a certain service. This could be a webservice but also directly the user.

By defining some simple interfaces, and use the MVVM design pattern we can create ViewModel implementations which do just this:

public interface IEditViewModel<TEntity>
{
    EditResult EditEntity(TEntity entityToEdit, DialogHandler dialogHandler);
}

public interface IChooseViewModel<TEntity>
{
    TEntity ChooseEntity(DialogHandler dialogHandler);
}

public class ChooseEntityService
{
    private readonly Container container;
    private readonly DialogHandler dialogHandler;

    public ChooseEntityService(Container container, DialogHandler dialogHandler)
    {
        this.container = container;
        this.dialogHandler = dialogHandler;
    }

    public TEntity ChooseEntity<TEntity>()
    {
        var viewModel = this.container.GetInstance<IChooseViewModel<TEntity>>();
        return viewModel.ChooseEntity(this.dialogHandler);
    }
}

In the window needing to choose a customer we inject ChooseService . This service will find the correct implementation and DialogHandler would be an implementation which shows the view through your favorite MVVM tool.

This answer goes into greater detail on this design.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM