1

I am working on a Revit plugin and I am forced to work through a command. This command has a parameter that I need to change information inside Revit: UIApplication.

From the command I open a new Window, this Window creates it's ViewModel through XAML:

<Window.DataContext>
    <!--Automatically creates an instance of the class-->
    <plugin:PluginViewModel />
</Window.DataContext>

I would like to create my ViewModel with the UIApplication parameter, which is supplied through the constructor of my Window. Is this the only way to do it?

public PluginWindow(UIApplication application)
{
   InitializeComponent();
   //DataContext has been initialized by InitializeComponent();
   var pluginVM = (PluginViewModel)DataContext;
   pluginVM.Application=application;
}

Or should I do it through the command?

var pw = new PluginWindow();
var pluginVM = (PluginViewModel)pw.DataContext;
pluginVM.Application=application;

Or is it possible to do in the XAML of the Window?

<Window.DataContext>
    <!--Automatically creates an instance of the class-->
    <plugin:PluginViewModel SomeUnknownMagicHere/>
</Window.DataContext>

The last one would be preferred.

I could also have the UIApplication available as a static variable somewhere, but this would be somewhat ugly, right?

ManIkWeet
  • 1,298
  • 1
  • 15
  • 36
  • There is no "correct" way to do it. There are many ways, and it's up to you to decide which works best for you. Signed, some idiot on the internet who may or may not have a valid opinion. –  May 27 '16 at 14:08
  • 2
    I'd inject the `PluginViewModel` already built up into the `PluginWindow` constructor. Having the View layer partially initialize your ViewModel seems like a poor design – Jonesopolis May 27 '16 at 14:08
  • The reason I want to do it through XAML is so that ReSharper doesn't add green lines to every binding and F12 functionality actually works. – ManIkWeet May 27 '16 at 14:21
  • There is a way to do it but you need to create an object in your xaml, with `x:Key` and then instead of setting the `DataContext` on your `Window` set it on your `Grid` or whatever is your first container. Then you can access the vm properties and assign them through xaml. HTH – XAMlMAX May 27 '16 at 14:37
  • 2
    I always cringe when I see someone hardcode `` in the XAML like this... this is such bad WPF design because you are saying this UI is now hardcoded to this specific instance of some object, and you can never use it with any other object instance, which kind of defeats the whole purpose of the visual tree, data bindings, and separation of UI and code. What you should have is `UIApplication` creating an instance of `PluginViewModel`, and just giving the VM to render with an Implicit DataTemplate. Or passing it to a Window management service of some kind to decide how to draw it – Rachel May 27 '16 at 15:46
  • 1
    As a side note, I also hate multi-window WPF applications. I would much rather swap out the content area for new "screens" or sections of the application, like [this](http://stackoverflow.com/a/12216068/302677) – Rachel May 27 '16 at 15:47
  • @Rachel Completely agree - 'View-First' WPF/MVVM is so often an anti-pattern that leads to this kind of tight coupling. – Andrew Hanlon May 27 '16 at 15:58
  • I came to the conclusion that it is indeed better to create the ViewModel first. Apparently you can set a "DesignContext" in XAML which is ignored during runtime, this solves my ReSharper issue. I will use multi-window WPF applications because it fits in the existing environment. – ManIkWeet May 30 '16 at 07:41

0 Answers0