I am trying to find the best practice for creating view models and services (service just talks to the server and return data back to view model). I have seen 2 different approaches.
For the second approach, you define a behavior on UserControl and on attach event you create an instance of view model and an instance of service and put them all together.
protected override void OnAttached()
{
var service = Activator.CreateInstance(ServiceType)
var viewModel = Activator.CreateInstance(ModelType);
base.AssociatedObject.DataContext = viewModel;
base.OnAttached();
}
and in your usercontrol xaml
<i:Interaction.Behaviors>
<be:ViewModelBehavior ViewModelType="{x:Type vm:ViewModel1}" ServiceType="{x:Type serv:Service1}"/>
</i:Interaction.Behaviors>
Is this a good use of behaviors, or I should just use viewmodel locator pattern.
Your behavior has one significant disadvantage - in each usercontrol you have to specify the behavior, ViewModelType (and ServiceType as well).
You can do following:
<UserControl x:Class="MyApp.HomePage" ....
local:ViewModelLocator.AutoWireViewModel="True">
...
</UserControl>
When you set the attached property to true, ViewModelLocator
will create the viewmodel instance and assign it to the usercontrol's datacontext. The ViewModelLocatator
uses naming convention to determine type of viewmodel. In this case it could be HomePageViewModel
, because the view type is HomePage
.
This approach is used by PRISM ViewModelLocator from Prism.Mvvm library, but I recommend you to write your own, since it's quite easy.
It is basically similar to your ViewModelBehavior
, but the re are two differences:
The behavior is implemented as attached property. It allows you to specify the behavior in Style, so it will be applied to any usercontrol that uses this style. You cannot specify Interaction.Behaviors in styles.
It uses naming convention instead of explicitly set ViewModelType
public class MyViewModel(IMyService service) {...}
//at application startup you setup the IoC container:
IoC.Setup<IMyService>(new MyService());
//later
var viewModel = IoC.GetInstance<MyViewModel>(); //MyService will be passed as to ctor