0

I have a fairly simple and standard MVVM WPF app. I am using TinyIoC as a containter to provide the underlying data and cache providers for the ViewModels. I am using TinyIoC because I want to also share this code with MonoTouch and Monodroid projects.

Every user control who's ViewModels are not dependent on resolving a data provider from TinyIoC are working fine when added to the XAML of the MainWindow.

The user controls who's ViewModels ARE using TinyIoC to resolve the data provider used get their data, cannot be instantiated in the designer view when added to the MainWindow.

Important note: everything works fine when I run the app, just the designers are broken - a big impediment.

Here is the basic code:

    // From App.xaml.cs
    private void HandleAppStartupEvent(object sender, StartupEventArgs e) {
        IDataStoreProvider store = new XmlDataStoreProvider();
        ICacheProvider cache = new DictionaryCacheProvider();

        TinyIoCContainer.Current.Register(store);
        TinyIoCContainer.Current.Register(cache);
    }

View / ViewModel / XAML binding standard implementation - nothing an issue here.

In the depths of the data layer, the IoC container is used to resolve which provider to use - the one that was set in the above code.

public static class Gateway
{
    private static IDataStoreProvider store;
    private static ICacheProvider cache;

    static Gateway() {
        store = TinyIoCContainer.Current.Resolve<IDataStoreProvider>();
        cache = TinyIoCContainer.Current.Resolve<ICacheProvider>();
    }

    // use the store and cache here...

}

Here is the exact error I get from the designer.

Unable to resolve type: Sample.Core.Data.IDataStoreProvider at TinyIoC.TinyIoCContainer.ResolveInternal(TypeRegistration registration, NamedParameterOverloads parameters, ResolveOptions options) in C:_dev\Sample\SampleSolution\Sample.Core\Utility\TinyIoC.cs:line 3281 at TinyIoC.TinyIoCContainer.Resolve(Type resolveType) in C:_dev\Sample\SampleSolution\Sample.Core\Utility\TinyIoC.cs:line 1314 at TinyIoC.TinyIoCContainer.ResolveResolveType in C:_dev\Sample\SampleSolution\Sample.Core\Utility\TinyIoC.cs:line 1433 at Sample.Core.Data.Gateway..cctor() in C:_dev\Sample\SampleSolution\Sample.Core\Data\Gateway.cs:line 14

I think I understand why I get this error - the App startup event is not fired to load the IoC before the designer loads and executes the user control inside the MainWindow.

Again important to note, the app works fine - IoC and everything. I would like to stop the designer loading error by either (in order of preference):

  • Understanding how to fix the code to properly work with the designer
  • Stub out the existing control data with mock data for the designer
  • Disabling this designer feature
IUnknown
  • 2,596
  • 4
  • 35
  • 52

2 Answers2

0

Are you trying to load data in the event handler for your Windows/container loaded event? Doing so has caused this type of problem for me in the past.

Sean Beanland
  • 1,098
  • 1
  • 10
  • 25
  • I also tried in the constructor but had the same problem. I am looking for a place I can initialize the container that will also work the Designer. – IUnknown Jul 13 '12 at 18:58
0

Here a solution to the second bullet (Stub out the existing control data with mock data for the designer)

Added the following code to the ViewModel constructor:

    public AdminViewModel(UserControl view) {
        this.view = view;

        var designMode = DesignerProperties.GetIsInDesignMode(view);

        if (designMode) {
            Items = new ObservableCollection<ItemModel>
                      {new ItemModel {Name = "Item1"}, 
                       new ItemModel {Name = "Item2"}};
        }
        else {
            Items= new ObservableCollection<ItemModel>(Gateway.GetItems());
        }   
    }

Although works, I have a couple concerns:

  • Pollutes the code with non-app logic
  • Forces me to pass a reference of the View to the ViewModel

I would prefer to make this more "Blend-able" and designer friendly in cleaner ways - any other thoughts?

IUnknown
  • 2,596
  • 4
  • 35
  • 52
  • If this is a complete answer to your own question, than this answer if fine. Otherwise it is better to update your question with this information (especially since this answer contains a question again) and remove this answer. – Steven Jul 14 '12 at 11:34