title: MVVM and DI with nested controls
body: <p>I've been using MVVM for WPF quite a while now but I've always been doing it this way:</p>
  
  <p><strong>ExampleView.xaml.cs</strong> (namespace: Example.Views)</p>
  
  <pre><code>public partial class ExampleView
  {
      public ExampleView()
      {
          InitializeComponent();
  
          var viewModel = new ExampleViewModel();
          DataContext = viewModel;
      }
  }
  </code></pre>
  
  <p>The <strong>ExampleView.xaml</strong> has no code concerning the <code>ExampleViewModel</code> except for bindings to properties.</p>
  
  <p><strong>ExampleViewModel.cs</strong> (namespace: Example.ViewModels)</p>
  
  <pre><code>public ExampleViewModel()
  {
      // No important code in here concerning this topic. Code here is only used in this class.
  }
  </code></pre>
  
  <p>Below is a simplified <strong>MainWindowView.xaml</strong>.</p>
  
  <pre><code>&lt;Window ...
          xmlns:views="clr-namespace:Example.Views"&gt;
      &lt;Grid&gt;
          &lt;views:ExampleView /&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>The <strong>MainWindowView.xaml.cs</strong> is similar to the ExampleView.xaml.cs. The <strong>MainWindowViewModel.cs</strong> has no important code concerning this topic.</p>
  
  <p>Lastly, the <strong>App.xaml</strong> contains the <code>StartupUri="Views/MainWindowView.xaml"</code>.</p>
  
  <p>If this is a good pattern or not, I got my application to work. Since the application is not maintainable by me alone anymore, 2-3 people are now working on it creating some problems. One person is doing the majority of the coding (ViewModels basically), one person is doing the GUI (Views) and one person is doing the "framework" coding. <em>(Using "" because this is not really a framework but I can't think of a better word for it.)</em></p>
  
  <p>Now, I'm the guy that is doing the framework coding and I've been reading up on several subjects like dependency injection and the code below is what I came up with using <code>UnityContainer</code> from Windows.</p>
  
  <p><strong>ExampleView.xaml.cs</strong> (namespace: Example.Views)</p>
  
  <pre><code>public partial class ExampleView
  {
      public ExampleView()
      {
          InitializeComponent();
      }
  }
  </code></pre>
  
  <p>The <strong>ExampleView.xaml</strong> has no code concerning the <code>ExampleViewModel</code> except for bindings to properties.</p>
  
  <p><strong>ExampleViewModel.cs</strong> (namespace: Example.ViewModels)</p>
  
  <pre><code>public string MyText { get; set; }
  
  public ExampleViewModel(ILocalizer localizer)
  {
      MyText = localizer.GetString("Title");
  }
  </code></pre>
  
  <p>Below is a simplified <strong>MainWindowView.xaml</strong>.</p>
  
  <pre><code>&lt;Window ...
          xmlns:views="clr-namespace:Example.Views"&gt;
      &lt;Grid&gt;
          &lt;views:ExampleView DataContext="{Binding ExampleViewModel}" /&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>The <strong>MainWindowView.xaml.cs</strong> is similar to the ExampleView.xaml.cs.</p>
  
  <p><strong>MainWindowViewModel.cs</strong></p>
  
  <pre><code>ExampleViewModel ExampleViewModel { get; set; }
  private readonly ILocalizer _localizer;
  private readonly IExceptionHandler _exHandler;
  
  public MainWindowViewModel(ILocalizer localizer, IExceptionHandler exHandler)
  {
      _localizer = localizer;
      _exHandler = exHandler;
  
      ExampleViewModel = new ExampleViewModel(localizer);
  }
  </code></pre>
  
  <p>Lastly, the <strong>App.xaml</strong> does not contains the <code>StartupUri="..."</code> anymore. It's now done in <strong>App.xaml.cs</strong>. It's also here where the `UnityContainer is initialized.</p>
  
  <pre><code>protected override void OnStartup(StartupEventArgs e)
  {
      // Base startup.
      base.OnStartup(e);
  
      // Initialize the container.
      var container = new UnityContainer();
  
      // Register types and instances with the container.
      container.RegisterType&lt;ILocalizer, Localizer&gt;();
      container.RegisterType&lt;IExceptionHandler, ExceptionHandler&gt;();
      // For some reason I need to initialize this myself. See further in post what the constructor is of the Localizer and ExceptionHandler classes.
      container.RegisterInstance&lt;ILocalizer&gt;(new Localizer()); 
      container.RegisterInstance&lt;IExceptionHandler&gt;(new ExceptionHandler());
      container.RegisterType&lt;MainWindowViewModel&gt;();
  
      // Initialize the main window.
      var mainWindowView = new MainWindowView { DataContext = container.Resolve&lt;MainWindowViewModel&gt;() };
  
      // This is a self made alternative to the default MessageBox. This is a static class with a private constructor like the default MessageBox.
      MyMessageBox.Initialize(mainWindowView, container.Resolve&lt;ILocalizer&gt;());
  
      // Show the main window.
      mainWindowView.Show();
  }
  </code></pre>
  
  <p>For some reason I need to initialize the Localizer and ExceptionHandler classes myself. The Localizer and ExceptionHandler constructors are found below. Both have constructors with all arguments that have a default value. Adding constructors without arguments like </p>
  
  <pre><code>public ExceptionHandler() : this(Path.Combine(Directory.GetCurrentDirectory(), "ErrorLogs", DateTime.Now.ToString("dd-MM-yyyy") + ".log")) { }
  </code></pre>
  
  <p>doesn't change a thing.</p>
  
  <pre><code>public Localizer(ResourceDictionary appResDic = null, string projectName = null, string languagesDirectoryName = "Languages", string fileBaseName = "Language", string fallbackLanguage = "en")
  {
      _appResDic = appResDic ?? Application.Current.Resources;
      _projectName = !string.IsNullOrEmpty(projectName) ? projectName : Application.Current.ToString().Split('.')[0];
      _languagesDirectoryName = languagesDirectoryName.ThrowArgNullExIfNullOrEmpty("languagesFolder", "0X000000066::The languages directory name can't be null or an empty string.");
      _fileBaseName = fileBaseName.ThrowArgNullExIfNullOrEmpty("fileBaseName", "0X000000067::The base name of the language files can't be null or an empty string.");
      _fallbackLanguage = fallbackLanguage.ThrowArgNullExIfNullOrEmpty("fallbackLanguage", "0X000000068::The fallback language can't be null or an empty string.");
      CurrentLanguage = _fallbackLanguage;
  }
  
  public ExceptionHandler(string logLocation = null, ILocalizer localizer = null)
  {
      // Check if the log location is not null or an empty string.
      LogLocation = string.IsNullOrEmpty(logLocation) ? Path.Combine(Directory.GetCurrentDirectory(), "ErrorLogs", DateTime.Now.ToString("dd-MM-yyyy") + ".log") : logLocation;
  
      _localizer = localizer;
  }
  </code></pre>
  
  <p>My big question now is if I'm approaching dependency injection correctly and if having several static classes that I initialize once are bad. Several topics I've read state that static classes are a bad-practice because of bad testability and tightly coupled code, but right now the tradeoffs of dependency injection are bigger than having static classes.</p>
  
  <p>Doing dependency injection correctly would be a first step in having less tightly coupled code though. I like the approach with the static <code>MyMessageBox</code> I can initialize once and that it's globally available in the application. This is mainly for "easy usage" I guess cause I can simply call <code>MyMessageBox.Show(...)</code> instead of injecting this all the way down to the smallest element. I have a similar opinion about the <code>Localizer</code> and <code>ExceptionHandler</code> because these will be used even more.</p>
  
  <p>A last concern I have is the following. Lets say I have a class with several arguments and one of the arguments is the <code>Localizer</code> (because this will be used in nearly any class). Having to add <code>ILocalizer localizer</code> every time </p>
  
  <pre><code>var myClass = new MyClass(..., ILocalizer localizer);
  </code></pre>
  
  <p>feels very annoying. This would push me towards a static Localizer I initialize once and having never to care about it anymore. How would this problem be tackled?</p>