7

Mam model widoku z konstruktorem, który wymaga usługi. Używam MvvmLight firmy GalaSoft, która wykorzystuje lokalizator usług do połączenia widoku z modelem widoku.Model widoku MVVM i inicjalizacja danych asynchronicznych

Uchwyty SimpleIOC zapewniające usługę konstruktorowi viewmodels są w porządku, ale muszę jakoś wypełnić mój obiekt viewmodel danymi ze źródła danych. Moje ViewModel wygląda tak: -

public class MainPageViewModel : ViewModelBase 
{ 
    private readonly GroupService _groupService; 
    private readonly GroupFactory _groupFactory; 
    private readonly ObservableCollection<GroupVM> _groupVms = new ObservableCollection<GroupVM>(); 


    public MainPageViewModel(Domain.Services.GroupService groupService, VMFactories.GroupFactory groupFactory) 
    { 
     _groupService = groupService; 
     _groupFactory = groupFactory; 
    } 

    public async Task Init() 
    { 
     var groups = await _groupService.LoadGroups(); 
     foreach (var group in groups) 
     { 
      GroupVms.Add(_groupFactory.Create(group)); 
     } 
    } 

    public ObservableCollection<GroupVM> GroupVms { get { return _groupVms; } } 
} 

Jakoś musi metoda init nazwać oczekiwany, ale nie wiem, w jaki sposób najlepiej to zrobić? Mogę myśleć o trzech opcji: -

  1. po prostu zadzwonić Init na konstruktora, ale nie czeka go (wiem, to jest to naprawdę złe praktyki)
  2. Wzywam Init na obiekcie ViewModelLocator, ale ponieważ nie mogę Zwróć zadanie, którego znowu nie mogę oczekiwać. Przy ładowaniu widoku rzuciłem DataContext na pewien rodzaj IAsyncViewmodel i czekam na metodę init.

Użyłem opcji 3 w poprzednim projekcie sklepu Windows 8, ale to po prostu źle się dzieje. Każda rada byłaby naprawdę doceniona!

Dzięki

Ross

Odpowiedz

7

Jestem ciekawy, dlaczego uważasz, że nie oczekujesz asynchronicznego połączenia złą praktyką. Moim zdaniem nie jest tak źle, o ile wiesz, co to oznacza, że ​​połączenie zostanie wykonane w tle i może wrócić w dowolnym momencie.

Zazwyczaj używam metody asynchronicznej w konstruktorze dla celów tworzenia danych czasu projektowania i nie czekam na to. Po prostu dbam o podnoszenie zdarzeń PropertyChanged i CollectChanged, w razie potrzeby, aby powiązania były aktualizowane i to wystarczy.

Cheers Laurent

+0

Dobra uwaga, była to "jedna z tych" rzeczy, które wziąłem, ale nie do końca się nad tym zastanawiałem. Tutaj jest trochę więcej informacji na temat: http://stackoverflow.com/questions/7261173/c-sharp-start-async-method-within-object-constructor-bad-practice Zasadniczo dzieje się tak, ponieważ gdy obiekt jest skonstruowany, wciąż jest " robienie rzeczy "być może nieoczekiwanie, a także bardzo trudno poradzić sobie z wyjątkami, które mogą wystąpić. Próbowałem obu sposobów i myślę, że wolę init w konstruktorze, ale nadal nie jestem pewien! –

+0

wskazówka: aby uniknąć "przeskoków" w Visual Studio wystarczy przypisać wartość zwróconego zadania do zmiennej typu dummy –

1

nie jestem tak obeznany z MvvmLight jak kiedyś było, ale próbowałem do czynienia z async konstruktorów w różny sposób.

Opcja (1) zawiera złożoności obsługi błędów. Opcja (3) wymusza dostęp do InitAsync.

wolę podejście async fabrycznego (np opcja (2), gdzie DataContext zatrzymałbym null aż zakończy inicjalizacji VM), ale to brzmi jak ViewModelLocator nie zadziała za to. Więc (na razie) musisz wybrać pomiędzy fabryką async, która nie używa IoC i jednej z innych opcji (1 lub 3), które nie są idealne.

Osobiście wyrzuciłbym IoC dla wiązania VM/View (do tego nie używam IoC, moje widoki zależą od moich maszyn wirtualnych) i używają metody fabrycznej async. Jednak inne opcje są całkowicie opłacalne, jeśli chcesz pozostać przy IoC. W przypadku maszyn wirtualnych myślę, że opcja (1) byłaby nieco lepsza niż opcja (3), jeśli zawsze miałbyś najwyższy poziom try/catch w swoich metodach.

+0

Dzięki Zostawię to pytanie otwarte na trochę dłużej, chciałbym usłyszeć opinie innych ludzi na ten temat. –

Powiązane problemy