5

Come sfondo, sto giocando con un'applicazione per Windows Store e un'applicazione Windows Phone 8 che condivide un singolo ViewModel (PCL).Quale codice viene eseguito come parte del tempo di progettazione XAML? In Visual Studio e Blend

Sto utilizzando MVVMLight e NInject/Local Service Locator per istanziare modelli e servizi di visualizzazione. Il che è fantastico e mi dà un accoppiamento veramente bello che è fantastico da testare ecc.

Tuttavia, ottenere il supporto dei dati del tempo di progettazione (passando da un diverso modulo NInject ecc.) È una scatola nera completa, e sebbene io ora farlo funzionare non ne sono molto contento, ed è stato principalmente attraverso tentativi ed errori.

Sto utilizzando la pratica standard di disporre di ViewModelLocator (istanziato come risorsa app) che estrae Visualizza modelli dall'indicatore di servizio. Questo viene sempre eseguito.

Il problema è che non posso dire quanto del mio codice venga effettivamente eseguito dall'editor in fase di progettazione. Quindi, per garantire che NInject sia inizializzato e il CSL collegato a NInject, devo avere un costruttore statico su ViewModelLocator che chiama la mia classe App per avviare NInject.

Questo mi sembra sbagliato. Quindi, davvero, mi piacerebbe sapere qual è la migliore pratica per questo, e se c'è effettivamente qualche documentazione/garanzia su quali parti dell'applicazione sono "avviate" mentre viene mostrata in fase di progettazione, e se ciò differisce tra App di Windows Store e app di Windows Phone 8.

ViewModelLocator.cs (frammento)

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 (frammento)

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 (frammento)

<?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> 

risposta

5

Il design editor di tempo dovrebbe istanziare solo la pagina che si sta modificando ed eseguire qualsiasi codice che viene chiamato mentre si fa questo:

  • Si analizza e crea un'istanza everyting al suo interno tra cui qualsiasi risorsa definita
  • Esegue il costruttore di pagine
  • Qualsiasi costruttore statico viene richiamato e i campi statici vengono inizializzati non appena si "tocca" t classe (sia i suoi membri statici o un'istanza)

Lei non ha detto come si voleva istanziare la vostra ViewModelLocator e inizializzare Ninject prima di cercare di ottenere il progettista working.Therefore è difficile dare suggerimenti su come riparare quello .

Come una raccomandazione generale per i dati di progettazione, ti consigliamo di attenersi allo DesignInstance markup che funziona con Windows Store App e Windows Phone 8.Hai solo bisogno di aggiungere il tempo di progettazione DataContext al Page markup:

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

sto istanziare la ViewModelLocator utilizzando le migliori pratiche MVVMLight, creando un'istanza nelle risorse App (io aggiornare la questione in un minuto) . Mi piacerebbe essere in grado di configurare NInject e CSL nella classe App da qualche parte - così com'è devo farlo all'interno di ViewModelLocator in quanto la classe App non sembra essere istanziata. –

+0

Aggiornato: dovresti essere in grado di vedere il binding da Main.xaml -> Application.Resources.ViewModelLocator -> ViewModelLocator.MainViewModel. Quello che non riesco a capire è come si accede a Application.Resources ma il costruttore non sembra essere. –

+0

@KieranBenton Sì, App.xaml è AFAIK referenziato come risorsa, la classe non è istanziata. Un'alternativa al tuo approccio è quella di istanziare la classe di cui hai bisogno manualmente per il progettista (utilizzando 'DesignerProperties.IsInDesignTool'). L'altro è di creare un'istanza del modello di visualizzazione del tempo di progettazione direttamente in XAML, come già suggerito. Hai davvero bisogno di DI in fase di progettazione? –

Problemi correlati