Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What code is executed as part of the XAML design time? In Visual Studio and Blend

As some background, I'm playing around with a Windows Store App and Windows Phone 8 application sharing a single ViewModel (PCL).

I'm using MVVMLight and NInject / Common Service Locator to instantiate view models and services. Which is great and gives me really nice loose coupling that is fantastic to test etc etc.

However, getting design time data support (by switching in a different NInject module etc) is a complete black-box, and although I now have it working I'm not very happy with it, and its been mainly through trial and error.

I'm using the standard practice of having a ViewModelLocator (instantiated as an app resource) that pulls View Models from the Service Locator. This always gets executed.

Problem is, I can't tell how much of my code is actually being executed by the design-time editor. So, to ensure that NInject is initialised and the CSL hooked into NInject, I have to have a static constructor on the ViewModelLocator that calls into my App class to kick-off NInject.

This seems wrong to me. So really, I'd like to know what the best practice for this is, and if there is actually any documentation / guarantees on which parts of the application are "started" whilst it is being shown at design time, and if that differs between Windows Store Apps and Windows Phone 8 apps.

ViewModelLocator.cs (snippet)

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

<?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>
like image 439
Kieran Benton Avatar asked May 01 '13 11:05

Kieran Benton


People also ask

What is Blend for Visual Studio code?

Blend for Visual Studio helps you design XAML-based Windows and Web applications. It provides the same basic XAML design experience as Visual Studio and adds visual designers for advanced tasks such as animations and behaviors.

How do I find the XAML code in Visual Studio?

To open the XAML Designer, right-click a XAML file in Solution Explorer and choose View Designer. to switch which window appears on top: either the artboard or the XAML editor.

What is XAML code?

XAML stands for Extensible Application Markup Language. It's a simple and declarative language based on XML. In XAML, it very easy to create, initialize, and set properties of an object with hierarchical relations. It is mainly used for designing GUIs.

How do I use XAML Designer in Visual Studio?

To open this page, choose the Tools menu and then choose Options. To access the XAML Designer property page, choose the XAML Designer node. Settings for the XAML Designer are applied when you open the document. So, if you make changes to the settings, you need to close and then reopen Visual Studio to see the changes.


1 Answers

The design time editor should only instantiate the page you are editing and execute any code that gets called while doing this:

  • It parses and instantiates everyting inside it including any resources you have defined
  • It executes the page constructor
  • Any static constructors will get called and static fields initialized as soon as you "touch" that class (either its static members or instantiate it)

You didn't say how you wanted to instantiate your ViewModelLocator and initialize Ninject before trying to get the designer working.Therefore it's difficult to give suggestion how to fix that.

As a general recommandation for design time data I'd recommend you stick with DesignInstance markup which works with both Windows Store Apps and Windows Phone 8. You just need to add design time DataContext to your Page markup:

<Page xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      d:DataContext="{d:DesignInstance viewModels:PageViewModel, IsDesignTimeCreatable=True}">
like image 85
Damir Arh Avatar answered Oct 29 '22 18:10

Damir Arh