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>
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. –
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. –
@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? –