2010-10-27 7 views
10

Próbuję poradzić sobie z pisaniem testowalnych ViewModels w Silverlight 4. Im obecnie używa światła MVVM.Silverlight Konstruktor wtrysku w widoku Model + tryb projektowania

Im przy użyciu AutoFac i IoCContainer wykonuje swoje zadanie dobrze. Jednak aby wstrzyknąć do konstruktora ViewModels, które są zobowiązane do Wyświetleń mam tego konstruktora łańcuchowym:

public UserViewModel() : this(IoCContainer.Resolve<IUserServiceAsync>()) 
    { 

    } 

    public UserViewModel(IUserServiceAsync userService) 
    { 
     if (this.IsInDesignMode) return; 

     _userService = userService; 
    } 

Które nie czuje czyste, ale jest najlepszym rozwiązaniem znalazłem do tej pory. To działa, a moja aplikacja działa zgodnie z życzeniem i można ją przetestować z odwróconą kontrolą.

Jednak z moim VM związany z moim zdaniem tak:

<UserControl.DataContext> 
      <ViewModel:UserViewModel /> 
</UserControl.DataContext> 

W moim XAML stronie atrybutów, tryb projektowania zarówno VS2010 i mieszanki robi praca.

Czy istnieje lepszy sposób na osiągnięcie tego, co próbuję w Silverlight, który nadal działa w trybie projektowania? Utrata trybu projektowania nie stanowi problemu, ale przydaje się podczas nauki XAML. Czysty sposób, w jaki nie ma łańcuchów, byłby fajny!

Zastanawiam się, czy możliwe jest użycie AutoFac/IoC do rozwiązania viewmodeli do widoków, zgodnie z powyższym podejściem markowania XAML i przejściem w dół tej trasy?

Dzięki.

Odpowiedz

10

Zamiast wdrażania pierwszego konstruktora, proponuję wdrożyć ViewModelLocator, tak:

public class ViewModelLocator 
{ 

    IoCContainer Container { get; set; } 

    public IUserViewModel UserViewModel 
    { 
     get 
     { 
      return IoCContainer.Resolve<IUserViewModel>(); 
     } 
    } 

} 

Następnie w XAML zadeklarować lokalizatora jako statyczny zasób:

<local:ViewModelLocator x:Key="ViewModelLocator"/> 

Podczas inicjalizacji W przypadku zastosowania, konieczne jest podanie lokalizatora z wystąpieniem kontenera:

var viewModelLocator = Application.Current.Resources["ViewModelLocator"] as ViewModelLocator; 
if(viewModelLocator == null) { // throw exception here } 
viewModelLocator.Container = IoCContainer; 

Następnie w XAML można użyć zasobu czysto:

<UserControl 
    DataContext="{Binding Path=UserViewModel, Source={StaticResource ViewModelLocator}}" 
    /> 
    <!-- The other user control properties --> 

Na czasie projektowania, można wdrożyć MockViewModelLocator:

public class MockViewModelLocator 
{ 

    public IUserViewModel UserViewModel 
    { 
     get 
     { 
      return new MockUserViewModel(); 
     } 
    } 

} 

uznaniu jej w XAML odpowiednio:

<local:MockViewModelLocator x:Key="MockViewModelLocator"/> 

I wreszcie użyj go w swojej kontroli użytkownika:

<UserControl 
    d:DataContext="{Binding Path=UserViewModel, Source={StaticResource MockViewModelLocator}}" 
    DataContext="{Binding Path=UserViewModel, Source={StaticResource ViewModelLocator}}" 
    /> 
    <!-- The other user control properties --> 

Możesz sprawić, że Twój modelowy lokalizator zwróci bezpieczne i łatwe do odczytania dane dla Blend do użycia, a podczas działania będziesz używał swojej prawdziwej usługi.

W ten sposób nie tracisz danych projektowych i nie musisz rezygnować z czystej metodologii wprowadzania zależności w modelach widoku.

Mam nadzieję, że to pomoże.

+0

Dzięki za szczegółową odpowiedź! – Jammin

Powiązane problemy