ViewModel 中的构造函数 [英] Constructor in ViewModel

查看:17
本文介绍了ViewModel 中的构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在 ViewModel 中有一个构造函数来初始化数据服务?

Is it possible to have a constructor in the ViewModel, which initializes the data service?

我的数据服务正在以类似于以下的方式访问数据存储的网络服务:

My data service is accessing the web-service of the data storage in a manner similar to this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections.ObjectModel;
    using Cirrious.MvvmCross.ViewModels;
    using Cirrious.MvvmCross.Commands;
    using MobSales.Logic.DataService;
    using MobSales.Logic.Base;
    using MobSales.Logic.Model;

    namespace MobSales.Logic.ViewModels
    {
        public class CustomersViewModel:MvxViewModel
        {
            ICustomerService custService;
        public CustomersViewModel(ICustomerService custService)
        {
            this.custService = custService;
            if (custService != null)
            {
                custService.LoadCustomerCompleted += new EventHandler<CustomerLoadedEventArgs>(custService_LoadCustomerCompleted);
            }
            loadCustomerCommand = new MvxRelayCommand(LoadCustomer);
            loadCustomerCommand.Execute();
        }


    private ObservableCollection<Customer> customers;

    public ObservableCollection<Customer> Customers
    {
        get { return customers; }
        set
        {
            customers = value;
            FirePropertyChanged("Customers");
        }
    }


    private CustomerViewModel customer;

    public CustomerViewModel Customer
    {
        get { return customer; }
        set
        {
            customer = value;
            FirePropertyChanged("Customer");
        }
    }


    private MvxRelayCommand loadCustomerCommand;

    public MvxRelayCommand LoadCustomerCommand
    {
        get { return loadCustomerCommand; }
    }

    public void LoadCustomer()
    {
        custService.LoadCustomer();
    }

    void custService_LoadCustomerCompleted(object sender, CustomerLoadedEventArgs e)
    {
        if (e.Error != null)
        {
            return;
        }

        List<Customer> loadedCustomers = new List<Customer>();
        foreach (var cust in e.Customers)
        {
            loadedCustomers.Add(new Customer(cust));
        }

        Customers = new ObservableCollection<Customer>(loadedCustomers);
    }

}

我收到异常但只能看到以下部分描述:

I am getting an exception but can only see the following partial description:

Cirrious.MvvmCross.Exceptions.MvxException:无法从定位器 MvxDefau 加载 MobSales.Logic.ViewModels.CustomersViewModel 类型的 ViewModel…

实现从 View 到 ViewModel 的绑定,正如我在这篇文章中所展示的:Android 中的 MVVMCross 绑定

The binding from View to ViewModel is realized as I've shown in this post: MVVMCross Bindings in Android

谢谢!

推荐答案

MvvmCross 的一个不寻常(自以为是的)特性是默认情况下它使用 ViewModel 构造函数参数作为导航机制的一部分.

One of the unusual (opinionated) features of MvvmCross is that by default it uses ViewModel constructor parameters as part of the navigation mechanism.

在我对传递的回答中用一个例子解释了这一点从 ViewModel 到另一个 View (MVVMCross) 的变量

基本思想是当 HomeViewModel 请求导航时使用:

The basic idea is that when a HomeViewModel requests a navigation using:

private void DoSearch()
{
    RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText });
}

然后这将使用传递给构造函数的 searchTerm 构造一个 TwitterViewModel:

then this will cause a TwitterViewModel to be constructed with the searchTerm passed into the constructor:

public TwitterViewModel(string searchTerm)
{
    StartSearch(searchTerm);
}

目前,这意味着每个 ViewModel 都必须有一个没有参数或只有字符串参数的公共构造函数.

因此,您的 ViewModel 未加载的原因是 MvxDefaultViewModelLocator 找不到适合您的 ViewModel 的构造函数.

So the reason your ViewModel isn't loading is because the MvxDefaultViewModelLocator can't find a suitable constructor for your ViewModel.

对于服务",MvvmCross 框架确实提供了一个简单的 ioc 容器,可以使用 GetService() 扩展方法最轻松地访问该容器.例如,在 Twitter 示例 ViewModel 之一包含:

For "services", the MvvmCross framework does provide a simple ioc container which can be most easily accessed using the GetService<IServiceType>() extension methods. For example, in the Twitter sample one of the ViewModel contains:

public class TwitterViewModel
    : MvxViewModel
    , IMvxServiceConsumer<ITwitterSearchProvider>
{
    public TwitterViewModel(string searchTerm)
    {
        StartSearch(searchTerm);
    }

    private ITwitterSearchProvider TwitterSearchProvider
    {
        get { return this.GetService<ITwitterSearchProvider>(); }
    }

    private void StartSearch(string searchTerm)
    {
        if (IsSearching)
            return;

        IsSearching = true;
        TwitterSearchProvider.StartAsyncSearch(searchTerm, Success, Error);
    }

    // ...
}

同理,在会议 BaseViewModel

如果您喜欢为 ViewModel 使用其他一些 IoC 容器或其他一些构造机制,那么您可以在 MvvmCross 中覆盖 ViewModel 构造.

If your preference is to use some other IoC container or some other construction mechanism for your ViewModels, then you can override the ViewModel construction within MvvmCross.

看看这个问题(和答案)关于如何做到这一点的想法 - 如何在MVVMCross应用程序中替换MvxDefaultViewModelLocator

Take a look at this question (and answers) for ideas on how to do this - How to replace MvxDefaultViewModelLocator in MVVMCross application

例如如果您愿意,那么调整该问题中的 MyViewModelLocator 示例以使用您的服务构建您的 ViewModel 应该相当容易.

e.g. if you want to, then it should be fairly easy for you to adjust the MyViewModelLocator example in that question to construct your ViewModel with your service.

这篇关于ViewModel 中的构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆