作为背景,我正在使用一个Windows Store应用程序和Windows Phone 8应用程序共享单个ViewModel(PCL)。
我正在使用MVVMLight和NInject / Common Service Locator来实例化视图模型和服务。这很不错,并且给了我非常好的松散耦合,非常适合测试等等。
然而,获得设计时数据支持(通过切换不同的NInject模块等)是一个完全的黑盒子,虽然我现在已经让它工作了,但我对它并不是很满意,它主要是通过试错来实现的。
我使用的是标准做法,即拥有一个ViewModelLocator(作为应用程序资源实例化),它从Service Locator中提取View Model。这总是被执行。
问题是,我无法确定我的代码有多少实际上被设计时编辑器执行。因此,为了确保NInject已初始化并且CSL已连接到NInject,我必须在ViewModelLocator上有一个静态构造函数,该函数调用我的App类启动NInject。
这似乎不对劲。所以,我想知道这方面的最佳实践是什么,是否有任何关于应用程序哪些部分“启动”而显示在设计时的文档/保证,以及这是否在Windows Store应用程序和Windows Phone 8应用程序之间有所不同。
ViewModelLocator.cs(片段)
我正在使用MVVMLight和NInject / Common Service Locator来实例化视图模型和服务。这很不错,并且给了我非常好的松散耦合,非常适合测试等等。
然而,获得设计时数据支持(通过切换不同的NInject模块等)是一个完全的黑盒子,虽然我现在已经让它工作了,但我对它并不是很满意,它主要是通过试错来实现的。
我使用的是标准做法,即拥有一个ViewModelLocator(作为应用程序资源实例化),它从Service Locator中提取View Model。这总是被执行。
问题是,我无法确定我的代码有多少实际上被设计时编辑器执行。因此,为了确保NInject已初始化并且CSL已连接到NInject,我必须在ViewModelLocator上有一个静态构造函数,该函数调用我的App类启动NInject。
这似乎不对劲。所以,我想知道这方面的最佳实践是什么,是否有任何关于应用程序哪些部分“启动”而显示在设计时的文档/保证,以及这是否在Windows Store应用程序和Windows Phone 8应用程序之间有所不同。
ViewModelLocator.cs(片段)
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 (snippet)
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(代码片段)
<?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>
DesignerProperties.IsInDesignTool
)。另一个方法是直接在XAML中实例化设计时视图模型,就像我已经建议的那样。你真的需要在设计时使用DI吗? - Damir Arh