Today I spent some time looking at how to organize my WPF application to use a Model View Controller design pattern. I ended up getting it to work fairly well but I am pretty dissapointed in the lack of support for this model directly.
Specifically I got hung up on the limitations around the ObjectDataProvider class. This is a DataSourceProvider object you can use to bind your controls against. You have two options with this data provider, you either specify an ObjectType or an ObjectInstance. If you specify the ObjectType then you end up with complete design time support for databinding against this provider, which is a wonderful thing in Blend 2. However, if you do this then the ObjectDataProvider will take it upon itself to create your instance based on the Type information you provided… which does not work if you want to specify an interface or an abstract class. Using the ObjectInstance approach will also give you design time support if you’re the instance you provide is also declared in Xaml but this has the same activation limitations as simply specifying the Type. So this is a huge problem for an MVC style application.
What I really wanted to do was to create interfaces for all of my Modelsobjects, such as IProduct and IPurchase. Then I could create some mock objects for my test environment and let the other developer create the real objects for the real application. Well how the heck do you use the ObjectDataProvider so that it’s possible to bind against an abstract Model, the real instance of which is created by the controller? I think the answer is that you cannot, well not without sacrificing design time databinding support at least.
After looking at it for a while I realized that if I set IsInitialLoadEnabled property of my ObjectDataSource to false then after the controller is set in my form I could set the ObjectInstance field to my Model provided by the controller, then call InitialLoad. This would work but no design time support 😦
You’d think that you could specify the ObjectType for design time support then, using the initial load disabled trick create the real object but you would be wrong. Doing this throws an exception, you cannot set both fields for some inexplicable reason. The next thing you’d think of would be to inherit from ObjectDataProvider, override a method that creates the instance and instead create an event such as LoadInstance so that your controller can pass in the instance instead… but once again you’d be wrong. It seems that the ObjectDataProvider does not really expose any virtual methods of much use.
My next thought is to try to create an MvcDataProvider that supports this functionality a little better. I’m a little hesitant to do this though because of the difficulties I’ve had in the past creating a DataSource for ASP.NET. What a nightmare that was, even a very simple one.
Other than this one problem (which I’m hoping is just an ignorance problem still) I have to say I am enjoying using WPF immensely. Maybe creating a new DataSourceProvider will be just as easy and intuitive as the rest of WPF.
If anybody has any insight on how to resolve this issue I’d love to hear it. If I end up creating an MvcDataProvider I’ll be sure to post it in another blog.