Silverlight Constructor injection into View Model + Design Mode

Próbuję uporać się z pisaniem testowalnych modeli w Silverlight 4. Im obecnie używa światła MVVM.

Używam AutoFac i IoCContainer wykonuje swoją pracę dobrze. Jednak aby wprowadzić do konstruktora ViewModels, które są powiązane z widokami mam ten konstruktor chaining:

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

    }

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

        _userService = userService;
    }
Która nie wydaje się czysta, ale jest najlepszą opcją, jaką do tej pory znalazłem. 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ązane z moim zdaniem tak:

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

W moich atrybutach strony XAML, Tryb projektowania zarówno w VS2010, jak i Blend nie działa.

Czy istnieje ładniejszy sposób, aby osiągnąć to, co próbuję w Silverlight, który nadal działa z trybem projektowania? Przegrana w trybie projektowania nie jest przeszkodą, ale będzie przydatna podczas nauki XAML. Czyściciel bez łańcuchów byłby miły!

Myślę, że możliwe jest użycie AutoFac / IoC do rozdzielania viewmodels do views, jak to było w przypadku znaczników XAML podejść wyżej i zejść tą trasą?

Dzięki.
Author: Jammin, 2010-10-27

1 answers

Zamiast implementować pierwszy konstruktor, proponuję zaimplementować ViewModelLocator, jak to:

public class ViewModelLocator
{

    IoCContainer Container { get; set; }

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

}

Następnie w XAML deklarujesz lokalizator jako statyczny zasób:

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

Podczas inicjalizacji aplikacji, konieczne jest podanie lokalizatorowi instancji kontenera:

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

Następnie w XAML możesz używać zasobu czysto:

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

Na czas projektowania można zaimplementować MockViewModelLocator:

public class MockViewModelLocator
{

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

}

Declare it in XAML odpowiednio:

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

I na koniec 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 lokalizator modelu mock view zwróci bezpieczne i łatwe do odczytania dane do użycia w Blend, a podczas wykonywania będziesz korzystać z prawdziwej usługi.

W ten sposób nie tracisz danych czasu projektowania i nie musisz poświęcać czystości metodologii iniekcji zależności w swoich modelach widoku.

Mam nadzieję, że to pomoże.
 10
Author: Murven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-27 14:27:29