WPF - 使用行为来实例化视图模型和服务

WPF - Using behaviors for instantiating view model and services

我正在尝试寻找创建视图模型和服务的最佳实践(服务只是与服务器对话,return 数据返回视图模型)。我见过两种不同的方法。

  1. 使用视图模型定位器
  2. 使用行为(我不确定这是否是好方法)

对于第二种方法,您在 UserControl 和附加事件上定义一个行为,您创建一个视图模型实例和一个服务实例并将它们放在一起。

protected override void OnAttached()
    {
        var service = Activator.CreateInstance(ServiceType)
        var viewModel = Activator.CreateInstance(ModelType);
        base.AssociatedObject.DataContext = viewModel;
        base.OnAttached();
    }

并在您的用户控件中 xaml

<i:Interaction.Behaviors>
    <be:ViewModelBehavior ViewModelType="{x:Type vm:ViewModel1}"  ServiceType="{x:Type serv:Service1}"/>
</i:Interaction.Behaviors>

这是对行为的良好使用,还是我应该只使用视图模型定位器模式。

您的行为有一个明显的缺点 - 在每个用户控件中,您必须指定行为、ViewModelType(以及 ServiceType)。

您可以执行以下操作:

<UserControl x:Class="MyApp.HomePage" ....
             local:ViewModelLocator.AutoWireViewModel="True">
   ...
</UserControl>

当您将附加的 属性 设置为 true 时,ViewModelLocator 将创建视图模型实例并将其分配给用户控件的数据上下文。 ViewModelLocatator 使用命名约定来确定视图模型的类型。在这种情况下,它可能是 HomePageViewModel,因为视图类型是 HomePage.

Prism.Mvvm 库中的 PRISM ViewModelLocator 使用了这种方法,但我建议您自己编写,因为它非常简单。

基本与你的ViewModelBehavior相似,但有两点不同:

  1. 该行为已按附件 属性 实现。它允许您在 Style 中指定行为,因此它将应用于任何使用此样式的用户控件。您不能在样式中指定 Interaction.Behaviors。

  2. 它使用命名约定而不是显式设置 ViewModelType


关于服务,应该作为参数传递给 viewmodel:您可以使用 IoC 模式。这是描述模式的伪代码:

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