5

Jako niektóre tło, bawię się z aplikacją Windows Store i aplikacją Windows Phone 8 współdzielącą pojedynczy ViewModel (PCL).Jaki kod jest wykonywany jako część czasu projektowania XAML? W Visual Studio i Blend

Używam MVVMLight i NInject/Common Service Locator do tworzenia instancji modeli i usług. Co jest świetne i daje mi naprawdę fajne luźne sprzężenie, które jest fantastyczne do testowania itp.

Jednak uzyskanie wsparcia danych czasu projektu (poprzez przełączenie w innym module NInject itp.) Jest kompletną czarną skrzynką, i chociaż teraz działa, nie jestem z niego zadowolony, a to głównie dzięki próbom i błędom.

Używam standardowej praktyki polegającej na posiadaniu ViewModelLocator (utworzonej jako zasób aplikacji), która ściąga Modele widoku z Lokalizatora usług. To zawsze zostaje wykonane.

Problem polega na tym, że nie mogę powiedzieć, ile mojego kodu jest faktycznie wykonywane przez edytor czasu projektowania. Tak więc, aby upewnić się, że NInject jest zainicjowany i CSL podłączony do NInject, muszę mieć statyczny konstruktor na ViewModelLocator, który wywołuje moją klasę App, aby uruchomić NInject.

Wydaje mi się to niewłaściwe. Tak naprawdę, chciałbym wiedzieć, jaka jest najlepsza praktyka w tym zakresie, i czy faktycznie istnieje dokumentacja/gwarancja, które części aplikacji są "uruchamiane", gdy są pokazywane w czasie projektowania, i jeśli to różni się pomiędzy Aplikacje Windows Store i aplikacje Windows Phone 8.

ViewModelLocator.cs (fragment)

public class ViewModelLocator 
{ 
    static ViewModelLocator() 
    { 
     System.Diagnostics.Debug.WriteLine("VML Start"); 
     var servicelocator = new NinjectServiceLocator(App.Kernel); 
     ServiceLocator.SetLocatorProvider(() => servicelocator); 
     System.Diagnostics.Debug.WriteLine("VML End"); 
    } 

    public AppViewModel AppViewModel 
    { 
     get { return ServiceLocator.Current.GetInstance<AppViewModel>(); } 
    } 

    public MainViewModel MainViewModel 
    { 
     get { return ServiceLocator.Current.GetInstance<MainViewModel>(); } 
    } 
} 

App.xaml.cs (fragment)

partial class App : Application 
{ 
    public static StandardKernel Kernel { private set; get; } 

    static App() 
    { 
     // Register dependencies & hook the service locator to use NInject under the hood 
     var servicemodule = ViewModelBase.IsInDesignModeStatic ? (NinjectModule)new DesignTimeModule() : new RunTimeModule(); 
     var viewmodelmodule = new ViewModelModule(); 
     App.Kernel = new StandardKernel(servicemodule, viewmodelmodule); 
    } 
} 

App.xaml (fragment)

<?xml version="1.0" encoding="utf-8"?> 
<Application RequestedTheme="Dark" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      x:Class="KieranBenton.LeaveNow.App.App" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:app="using:KieranBenton.LeaveNow.App" 
      xmlns:dependencies="using:KieranBenton.LeaveNow.App.Dependencies" 
      mc:Ignorable="d"> 
    <Application.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       ... 
      </ResourceDictionary.MergedDictionaries> 
      <dependencies:ViewModelLocator x:Key="ViewModelLocator" 
              d:IsDataSource="True" /> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 

Main.xaml

<tcdcontrols:LayoutAwarePage x:Name="pageRoot" 
          x:Class="KieranBenton.LeaveNow.App.Pages.Main" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:tcdcontrols="using:TCD.Controls" 
          xmlns:vm="using:KieranBenton.LeaveNow.ViewModel" 
          mc:Ignorable="d" 
          DataContext="{Binding MainViewModel, Source={StaticResource ViewModelLocator}}"> 
    <Page.Resources> 
     <!-- Collection of grouped items displayed by this page, bound to a subset of the complete item list because items in groups cannot be virtualized --> 
     <!-- NOTE: Ridiculous lengths to get this working - see http://www.ralbu.com/post/2012/11/18/Building-WinRT-Windows-8-Grouped-items-using-MVVMLight.aspx --> 
     <CollectionViewSource x:Name="groupedItemsViewSource" 
           Source="{Binding Journeys}" 
           d:Source="{Binding Journeys, Source={d:DesignInstance Type=vm:Main, IsDesignTimeCreatable=True}}" 
           IsSourceGrouped="true" 
           ItemsPath="Routes" /> 
    </Page.Resources> 

Odpowiedz

5

Konstrukcja czas redaktor powinien instancji tylko edytowana strona i wykonać dowolny kod, który jest wywoływana podczas gdy to robi:

  • Analizuje i instancję everyting wewnątrz jest w tym wszelkie zdefiniowane zasoby:
  • Wykonuje konstruktor strony
  • Wszelkie statyczne konstruktory zostaną wywołane, a statyczne pola zostaną zainicjalizowane, gdy tylko "dotkniesz" tha t klasa (zarówno statycznej członków lub instancję)

nie powiedziałeś jak chciałeś instancję swoje ViewModelLocator i zainicjować Ninject przed próbuje projektanta working.Therefore trudno dać sugestię jak to naprawić .

Jako ogólne zalecenie dotyczące danych o czasie projektowania, polecam trzymać się z numerem DesignInstance markup, który współpracuje z aplikacjami Windows Store i Windows Phone 8.Trzeba tylko dodać czas projektowania DataContext do Page znaczników:

<Page xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     d:DataContext="{d:DesignInstance viewModels:PageViewModel, IsDesignTimeCreatable=True}"> 
+0

mam uruchamianiu tego ViewModelLocator wykorzystaniem najlepszych praktyk MVVMLight, tworząc instancję w zasobach App (będę aktualizować pytanie w minutę) . Chciałbym być w stanie ustawić NInject i CSL w klasie App gdzieś - tak jak to jest, muszę to zrobić wewnątrz ViewModelLocator, ponieważ klasa App wydaje się nie mieć instancji. –

+0

Zaktualizowana - powinieneś być w stanie zobaczyć powiązanie z Main.xaml -> Application.Resources.ViewModelLocator -> ViewModelLocator.MainViewModel. Nie mogę zrozumieć, w jaki sposób Application.Resources jest dostępny, ale konstruktor nie jest. –

+0

@KieranBenton Tak, App.xaml jest AFAIK odwoływany tylko jako zasób, klasa nie jest instancjonowana. Jedną z alternatyw dla twojego podejścia jest utworzenie instancji klasy, którą potrzebujesz ręcznie dla projektanta (przy użyciu 'DesignerProperties.IsInDesignTool'). Druga polega na utworzeniu modelu widoku czasu projektu bezpośrednio w XAML, jak już sugerowałem. Czy naprawdę potrzebujesz DI w czasie projektowania? –