什么代码作为XAML设计时的一部分执行?在Visual Studio和Blend中

Kie*_*ton 5 xaml design-time dependency-injection windows-phone windows-store-apps

作为一些背景知识,我正在使用Windows Store应用程序和Windows Phone 8应用程序共享一个ViewModel(PCL).

我正在使用MVVMLight和NInject/Common Service Locator来实例化视图模型和服务.这是伟大的,给我非常好的松耦合,这是很棒的测试等等.

然而,获得设计时数据支持(通过切换不同的NInject模块等)是一个完整的黑盒子,虽然我现在有它工作我对它不是很满意,它主要是通过反复试验.

我正在使用标准做法ViewModelLocator(实例化为app资源)从服务定位器中提取View Models.这总是被执行.

问题是,我无法确定设计时编辑器实际执行了多少代码.因此,为了确保初始化NInject并将CSL挂钩到NInject,我必须在其ViewModelLocator上调用一个静态构造函数App来启动NInject.

这对我来说似乎不对.实际上,我想知道最佳做法是什么,以及是否有任何文档/保证应用程序的哪些部分在设计时显示"启动",如果它们之间存在差异Windows应用商店应用和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>(); }
    } 
}
Run Code Online (Sandbox Code Playgroud)

App.xaml.cs(片段)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

Dam*_*Arh 5

设计时编辑器应该只实例化您正在编辑的页面并执行在执行此操作时调用的任何代码:

  • 它解析并实例化其中的每个内容,包括您定义的任何资源
  • 它执行页面构造函数
  • 只要您"触摸"该类(其静态成员或实例化它),任何静态构造函数都将被调用并初始化静态字段

ViewModelLocator在尝试让设计师工作之前,你没有说你想如何实例化和初始化Ninject.因此很难给出建议如何解决这个问题.

至于设计时数据的通用recommandation我建议你坚持使用DesignInstance标记它与Windows商店应用程序和Windows Phone 8,你只需要设计时添加作品DataContext到您的Page标记:

<Page xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      d:DataContext="{d:DesignInstance viewModels:PageViewModel, IsDesignTimeCreatable=True}">
Run Code Online (Sandbox Code Playgroud)