views:

510

answers:

2

Ok, I'm pulling my hair out over this, so any help will be hugely appreciated!

I'm building a WPF application using the MVVM pattern.

In an attempt to get data in at design time I am using the Ninject dependency injection framework in conjunction with a service locator (much like the example in an article at http://jonas.follesoe.no/YouCardRevisitedImplementingDependencyInjectionInSilverlight.aspx

(as I'm using WPF and not Silverlight I check for design time properties slightly differently but otherwise I believe it is applicable).

I can't get it to work at design time, no matter what I do the binding doesn't seem to even get called. It works fine at runtime.

Here's the code for my Ninject module:

public class ViewModelModule : StandardModule
{
    public override void Load()
    {
        bool isRuntime = !ViewModelBase.IsInDesignMode;

        if (isRuntime)
        {
            Bind<IViewModel>().To<MyViewModel>();                
        }
        else
        {
            Bind<IViewModel>().To<MyDesignTimeViewModel>();
        }
    }
}

MyDesignTimeViewModel is a plain CLR object that returns hardcoded data in place of all the same properties on MyViewModel.

The Service Locator is as follows:

 public class ViewModelLocator
 {
    private static IKernel kernel;

    static ViewModelLocator()
    {
        if (kernel == null)
        {
            kernel = new StandardKernel(new ViewModelModule());
        }
    }      

    public IViewModel ViewModel
    {
        get
        {
            var vm = kernel.Get<IViewModel>();
            return vm;
        }
    }
}

And the XAML binds the DataContext of the page as follows (though I've tried a few different ways of declaring it, all with the same result):

<Page.DataContext>
    <Binding Source="{StaticResource viewModelLocator}" Path="ViewModel" />        
</Page.DataContext>

(where the viewModelLocator is declared in a ResourceDictionary that is merged at the top of this file).

As I said this works fine at runtime, even if I switch my Ninject binding to use MyDesignTimeViewModel at runtime it successfully displays the dummy data. I've got a dummy converter in one of my bindings to see what gets passed through and this gets called at runtime but not at design time (I've been frantically debugging a design time instance using a seperate Visual Studio process all day, as per the MSDN recommendations!)

At design time the Ninject binding goes ahead, along with the kernel instantiation. Then the viewModel gets called for and it returns a DesignTimeViewModel, along with all my hardcoded data. But the actual binding to any of the properties on the viewmodel never seem to get called (the dummy converter breakpoint never gets hit).

I really can't see what I'm doing wrong. Any pointers in any direction would be greatly appreciated as at this stage I'm just baffled. Thanks :)

+1  A: 

Hi, Random Sequence :)!

Here are couple things to try:

  1. While you are debugging designer, check whether you have any warnings/errors.
  2. Try to snoop your designer with latest version of Snoop, which allows you to attach to the Visual Studio.
  3. Try to debug bindings. Maybe something interesting comes out.

And don't forget to check DataContexts :).

Hope at least something would help.

Cheers

Anvaka
Ok, an update:This must be something to do with the way the Visual Studio WPF Designer works vs the Expression Blend designer. It turns out that this works as expected in Blend (ie the DesignViewModel gets instantiated at design time, while the 'normal' ViewModel works as usual at runtime) but not in Visual Studio (fine by me as I wanted Blend anyway!).Perhaps someone with more knowledge of the WPF designers can come along and explain?!In the meantime I'll accept this answer as these are all great tips, but I can see nothing that explains this not working in the VS2008 designer.
randomsequence
When you were talking about debugging designer you talked about Blend or Visual Studio? How do you calculate ViewModelBase.IsInDesignMode?
Anvaka
My initial question was in Visual Studio (I hadn't opened Blend until this morning as I assumed they worked similarly at design time).ViewModelBase.IsInDesignMode looks at DesignerProperties.IsInDesignModeProperty in WPF mode, and HtmlPage.IsEnabled in Silverlight mode (this is WPF). I'm sure it is correctly detecting design mode.
randomsequence
A: 

Maybe the new design-time features of Visual Studio 2010 and Expression Blend 4 are an option for you.

How it works is shown in the BookLibrary sample application of the WPF Application Framework (WAF). Please download the .NET4 version.

jbe