2012-05-09 74 views
4

是否有可能在視圖模型中有一個構造函數來初始化數據服務? (不要誤會我的意思,我的數據服務正在訪問數據存儲的Web服務)類似這樣的東西(被問到,因爲我得到了ViewLoader引發的異常「無法加載ViewModel ...」而且它不會顯示整個例外...):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 ...

從View到ViewModel的綁定被實現,就像我在這篇文章中發佈的那樣:MVVMCross Bindings in Android

謝謝!

+0

我對ViewModels的理解是,它的確沒有與提取數據等有關。 – Styxxy

+1

是的,我只會初始化(錯誤的單詞...批准會更好)我的數據服務。獲取數據會發生在別的地方。你可以看到,我有一個加載完成的事件... – Martin

+1

如果它沒有發生在你的ViewModel中,爲什麼你的ViewModel必須有這個數據服務? – Styxxy

回答

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框架確實提供了可使用的GetService<IServiceType>()擴展方法是最容易找到的簡單的IoC容器。例如,在視圖模型的Twitter sample一個包含:

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


消耗如果您喜歡使用一些其他的IoC容器或一些其他的ViewModel構建機制,那麼你可以重寫MvvmCross中的ViewModel構造。

看看這個問題(和答案)的想法如何做到這一點 - How to replace MvxDefaultViewModelLocator in MVVMCross application

例如如果你願意,那麼你應該很容易調整MyViewModelLocator這個問題的例子來構建你的ViewModel和你的服務。

+0

ok,理解(多次閱讀後)。所以我不使用MVVM中ViewModels的構造函數。如果我把它正確的構造函數是爲了數據傳遞的目的,因此只適用於字符串。 – Martin

+0

在MvvmCross是的,這是默認行爲 - 但如果你想要不同的行爲,那麼很容易覆蓋默認 - 寫你覺得最適合你的應用程序的代碼:) – Stuart

+0

不,我不會重寫它們,我不想離開約定,確保它具有可移植性和可重用性。非常感謝。 – Martin