是否可以在视图模型中使用构造函数,初始化数据服务? (不要误解我的意思,我的数据服务正在访问数据存储的Web服务)这样的事情(问我因为我得到ViewLoader抛出的异常“无法加载ViewModel ......”而且它没有显示整个例外......):
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);
}
}
完整的异常是:Cirrious.MvvmCross.Exceptions.MvxException:无法从定位器MvxDefau加载类型MobSales.Logic.ViewModels.CustomersViewModel的ViewModel ...
从View到ViewModel的绑定实现就像我在这篇文章中发布的那样:MVVMCross Bindings in Android
谢谢!
答案 0 :(得分:5)
MvvmCross的一个不同寻常的(固定的)功能是默认情况下它使用ViewModel构造函数参数作为导航机制的一部分。
我在对Passing on variables from ViewModel to another View (MVVMCross)
的回答中举例说明了这一点基本思想是当HomeViewModel使用以下命令进行导航时
private void DoSearch()
{
RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText });
}
然后这将导致构建TwitterViewModel,并将searchTerm传递给构造函数:
public TwitterViewModel(string searchTerm)
{
StartSearch(searchTerm);
}
目前,这意味着每个ViewModel必须有一个没有参数或只有字符串参数的公共构造函数。
因此,未加载ViewModel的原因是因为MvxDefaultViewModelLocator无法为ViewModel找到合适的构造函数。
对于“服务”,MvvmCross框架确实提供了一个简单的ioc容器,可以使用GetService<IServiceType>()
扩展方法轻松访问它。例如,在Twitter sample其中一个ViewModel包含:
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);
}
// ...
}
同样,您可以在Conference BaseViewModel
中查看会议服务数据的使用情况如果您的偏好是为ViewModel使用其他一些IoC容器或其他构造机制,那么您可以在MvvmCross中覆盖ViewModel构造。
看一下这个问题(和答案),了解如何做到这一点 - How to replace MvxDefaultViewModelLocator in MVVMCross application
e.g。如果您愿意,那么您应该很容易调整该问题中的MyViewModelLocator
示例,以便使用您的服务构建ViewModel。