I may be going about this all wrong, but I thought I was on the right path. I'm building a WPF app for the first time and am still getting used to some of the ways things are done.
My Thinking
- My goal is to make my ViewModel class more testable.
- The ViewModel depends on a service class and wouldn't be functional without it.
- Therefore, it seems to make sense to me to inject the service into the ViewModel so that I can also start mocking it for testing purposes.
What I did
- Made a XAML reference to my view model, which is called "UploaderViewModel":
<Window.DataContext> <viewModels:UploaderViewModel> </viewModels:UploaderViewModel> </Window.DataContext>
NOTE: This works fine before I try to do the injection
- Set up structure map in my app.xaml.cs file:
void App_Startup(object sender, StartupEventArgs eventArgs) { ContainerBootstrapper.BootstrapStructureMap(); ProcessStartupArguments(eventArgs); }
Which calls my bootstrapper class:
public static class ContainerBootstrapper
{
public static void BootstrapStructureMap()
{
ObjectFactory.Initialize(
x => x.For<IVEDocumentService>().Use<VEDocumentService>()
);
}
}
I then have my UploaderViewModel class take the IVEDocumentService as a Constructor parameter:
public UploaderViewModel(IVEDocumentService documentService) { _documentService = documentService; //other unrelated code below this }
What's Going Wrong
I'm receiving an XAML error that says there's no default constructor found for the ViewModel, which makes sense, since I have no UploaderViewModel()
, only UploaderViewModel(IVEDocumentService documentService)
.
Question
- What's the best way to resolve this?
- Should I create an UploaderViewModel() constructor and make StructureMap call UploaderViewModel with an instance of the service, or is there a better way?
Update 1 -- Attempting to Use a Resource Dictionary, StructureMap error.
Based on this SO Answer to a similar question, I tried:
- Updating my App_Startup to add an instance of the UploaderViewModel to a resources dictionary:
void App_Startup(object sender, StartupEventArgs eventArgs) { ContainerBootstrapper.BootstrapStructureMap(); var uploaderViewModel = new UploaderViewModel(new Container().GetInstance<IVEDocumentService>()); Current.Resources["UploaderViewModel"] = uploaderViewModel; ProcessStartupArguments(eventArgs); }
- Added
DataContext="{StaticResource UploaderViewModel}"
to my<Window>
declaration - Commented out my
<viewModels:UploaderViewModel/>
declaration
Upon doing this, StructureMap now throw an error:
"StructureMap Exception Code: 202No Default Instance defined for PluginFamily