I hope someone can shine some light on best practise for my usecase.
I am using mvvm light and the simpleIoC container in a wpf usercontrol. I register my model and view models, dataservice and designtime service to it (very much according to mvvm light sample code)
The SimpleIoC container usage examples that I have seen seems to always treat the container as static / global for GalaSoft namespace.
But if I would create two instances of my WPF control in the same application I of course want each user control to have its own set of VMs and Model instance. So basically its own set of SimpleIoC registered instances. How would I best accomplish that when the default IoC container seems to be a static object?
When you getinstance you can optionally provide a key. Although you get a singleton per type by default this generates another cached version of that type per key. Meaning you could use a guid or something as a key per instance you require.
There's a potential problem though. If you getinstance 100 different versions then they're all in memory for the lifetime of your app.
You're probably ok if this is just going to be a few instances.
Any more and you're probably best using a more sophisticated di container. SimpleIoC is only intended for simple use cases.
You can, however, use a factory method when you getinstance. This is not to my taste, but if you really wanted to use simpleioc then it's something to consider.
You can read more from laurent bugnion here.
https://msdn.microsoft.com/en-us/magazine/jj991965.aspx
That's what the factory pattern is designed to solve, you create a class that creates your control view models and you inject that instead.
Better separation of concerns too.
How would I best accomplish that when the default IoC container seems to be a static object?
Don't use the default container but create your own instance of the SimpleIoc class:
User Control A:
SimpleIoc containerA = new SimpleIoc();
containerA.Register<ViewModel>();
...
ViewModel vm = containerA.GetInstance<ViewModel46>();
User Control B:
SimpleIoc containerB = new SimpleIoc();
...
Related
I'm currently facing one of the most discussed problems in MVVM: I have a complex Model in my WPF application and I'm not sure how I should display its data to the View.
According to many answers here on StackOverflow and also to this article there are two ways:
to wrap the Model inside the ViewModel by adding a property in the ViewModel for each property in the Model
to expose the Model directly to the view without replicating the properties.
What I understood so far is that the first approach is better from a theoretical point of view, while the second one is a quick shortcut that should be avoided.
In the same article I previously linked, the author writes the following:
In reviewing the sample application from the Caliburn framework, they implement the VM using option 2.
I took a look at the Caliburn.Micro documentation and unfortunately it just uses a simple ViewModel without a real Model, so I don't know how to verify this statement.
Is the author right? Since I'm using Caliburn.Micro should I use the second approach instead of the first one in order to be more "compliant" with the framework implementation?
Since I'm using Caliburn.Micro should I use the second approach instead of the first one in order to be more "compliant" with the framework implementation?
No. Caliburn.Micro is just an MVVM library. How you implement the actual MVVM pattern is entirely up to you.
I agree with #Marek Dzikiewicz that you should wrap the model in a view model class that may implement the INotifyPropertyChanged interface and provide any other UI specific functionality. This code doesn't belong to a business object. You could refer to my answer here for more information:
Reuse the same models in ASP.NET MVC and WPF MVVM
Obviously if the model class is indeed a UI specific class that is not used in any other application and doesn't contain any business logic that is used on the server side, you could modify this class and bind to it directly. But then it is kind of a (sub) view model after all.
Usually it is better to expose view models because that allows you to add additional properties to control the way the data is displayed (for example formatting or concatenating data). However, if you don't need that, there is nothing wrong in exposing the model classes directly.
With Castle Windsor every component is tracked by default, even if it's the lifestyle is configured as transient. How do I deal with this in a WPF MVVM application? I don't want to create (or register using the Typed Factory Facility) a factory for every ViewModel type and release every instance I create, but I accept it if that's the only solution.
I know about the NoTrackingReleasePolicy, and I also know that using it means you're probably doing something wrong, but could it perhaps work for MVVM with singleton services and transient ViewModels only?
Is there perhaps a possibility to use child containers for the ViewModels which use the NoTrackingReleasePolicy?
Assume that there is WPF application which uses MVVM light toolkit.
Good example of this toolkit is Locator.
It is great it contains SimpleIoC which enables us to register Services and be Interface Driven.
Sometimes Locator constructor can really grows.
Unfortunatelly besides registering Interfaces it contains some logic as.:
if(SimpleIoc.Default.GetInstance<MainViewModel>().LoadProject())
{
var project = SimpleIoc.Default.GetInstance<MainViewModel>().LoadedProject
SimpleIoc.Default.Register<ConfigService>(new Service(project))
}
It was only an example - what If I need more logic during Locator Constructor.
Maybe my Services Architecture is wrongly created since they they are not independent or Maybe in such cases I should resign Locator usage - but then I will lost DI.
Another things is that in few ViewModels there is Reference to
Locator.GetInstance which I found another not a good practise since it should be injected via contructor to enable testability.
Another aspect is Using it correctly with AvalonDock.
AvalonDock is great anchorable control which enable to prepare apps which could be similar to such apps as Visual Studio with anchorable, dockable panes.
This panes are actualy another ViewModels which are bound to AvalonDock via property.
MainViewModel has property Tools = new Tools[] { ViewModel1, ViewModel2}
But each ViewModel was registered in Locator.
therefore I am using (violate DRY) them in MainViewModel as
Property getter: Locator.GetInstance()
which is in my opinion another bad example - even not safe.
What if any service required by Avalon Tool ViewModel1 is not registered yet but it is invoked via getter during MainViewModel instantiation.
It started to be a mismatch. Do you have any good practise?
I found many examples such as Workspaces (MainViewModel) but nobody used at the same time Locator which I found very useful.
I would like to keep Locator because I consider it to be a good thing which enables mme to have my project testable thanks to dependency Injection and Interface Driven.
Any Ideas suggestions? I would be thankful.
I'd avoid this. As you rightly point out, there is a lot more going on here then simply registering types.
Instead, I'd pass the ConfigService instance to the Viewmodel in its constructor. As long as it is register first, you can IOC the config service and view model.
SimpleIOC.Register<IViewModel>(()=>{return new ViewModel(SimpleIOC.GetInstance<IConfigService>())});
... That's all from memory so might not be accurate but does show the custom constructor idea from SimpleIOC.
In your view model constructor you can then call the service .Register method passing itself as a parameter.
That keeps the 'knowledge' in your view model and your locator stays focused on doing what it should.
I can create views myself using IoC without any problems if all dependencies that my view constructor needs as arguments are registered within my IoC-container.
But in case if I try to extensively use DataTemplates, then WPF creates my views. And in case if view has no default constructor, then WPF will fail and crash whole app. Thus my question is - are there any extensibility points in WPF so that I can provide a view factory to it, which will be able to create my views even when they do not have default constructor?
Unfortunately, and to my knowledge, the answer is no. I was just looking for the same thing, but WPF can only create user controls with parameterless constructors.
One solution would be to use the Service Locator pattern, where your UserControl has access to the container in its constructor and Resolves its dependency by itsself. I personally don't like this pattern. Some call Service Locator an anti-pattern, and in the long run, it can get you into trouble.
I am working on a WPF application using MVVM pattern. I need to do data validation(using Data Annotations) for my data entry screens.
But the tricky part to write a common piece of code is rather than using simple property I need to use properties with are calling GetValue and SetValue method. But my entities are being generated by entity framework using templates and modifying template to achieve this things seems very difficult.
I am using this technique to validate my data
http://blogs.microsoft.co.il/blogs/tomershamam/archive/2010/10/28/wpf-data-validation-using-net-data-annotations-part-ii.aspx
http://blogs.microsoft.co.il/blogs/tomershamam/archive/2010/10/11/notifyingobject-for-wpf-amp-silverlight.aspx
If there is better and authentic way to validate the entity data, i'll be more than happy to change my approach or if I need to change the template then please point me to some great reference.
Firstly. Really bad idea to do this, not because it is hard, but due to that you need to inherit DependencyObject. DependencyObject is an STA Threaded class. You won't be able to use a worker thread to instantiate your objects, which means you can't use a worker thread to use Entity Framework.
Now, I suggest you use the MVVM pattern with WPF. You should have a View bind to a ViewModel, which then binds to your Entity Framework POCO objects.
You can try IValidateObject for you validation https://stackoverflow.com/questions/13917890/mvc4-custom-validation-via-ivalidateobject-validate-method-not-working
I personally however prefer the FluentValidation library.