wpfxamlmvvmbehaviorviewmodellocator

WPF - Using behaviors for instantiating view model and services


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.

  1. Using view model locator
  2. Using behaviors (I am not sure if this is good approach)

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.


Solution

  • 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:

    1. 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.

    2. It uses naming convention instead of explicitly set ViewModelType


    Regarding the service, that should be passed as a parameter to viewmodel: You can use IoC pattern. This is pseudocode, that describes the pattern:

    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