Where should I set the DataContext - code behind or xaml? - wpf

(honestly I searched and read all the 'related questions' that seemed relevant - i do hope i didn't "miss" this question from elsewhere but here goes...)
There are two different ways (at least) to set the DataContext. One can use XAML or one can use the code behind.
What is the 'best practice' and why?
I tend to favor setting it in XAML because it allows a designer to define collections on their own but I need 'ammunition' on why it's a best practice or why I'm crazy and the code behind is the bomb...

A third way you might look at is using a locator service. I usually have one class that is responsible for the creation of all my DataContext(VM's in most cases for me) and I create an instance of that class in the App.xaml Resources. Then I bind the DataContext in the XAML of each individual page.
i.e.
<Page DataContext="{Binding ViewModel,Source={StaticResource Locator}}" >

I think it depends on what you are setting the DataContext to, and ultimately personal preference.
I personally always do it in the code behind of my views because I find it overall cleaner, and it was how I was taught MVVM. Another thing to keep in mind is, there are times you may need to change your datacontext depending on what you are working with. If this is the case it's much cleaner/easier to do in the code behind rather than in XAML.

As you can see by the answers so far opinion is divided. In truth there is no best practice (I do get bee in my bonet about discusions of "best practice" in the Silverlight world, its way too young for best practice to be truely known.)
The reality actually is that you can't set the "data context" in Xaml. Unless you actually construct an object instance like this:-
<UserControl>
<UserControl.DataContext>
<local:MyDataProviderThing />
Ultimately something external has to assign either the DataContext property directly or indirectly via another property or via binding (as in Stephan's answer). Its this external context which is dictates whether it makes sense to do it in Xaml or not. Many MVVM solutions use a binding in Xaml, in some cases simply to avoid there having to be any code at all in code-behind rather than it truely being "better". Others set up the DataContext in code using a base class that your control derives from.

DataContext of the user control/view I assume? One advantage of setting data context in the code behind is the availability of dependency injection. Your DI container can take care of any dependencies for you dynamically at run-time.
With this pattern, I frequently set a view's Blend design DataContext in xaml using d:DataContext. The "design version" can provide mock data for use in Blend, while the true implementation is resolved at run-time.

Related

viewmodel have to be public. How should I deal with that?

Pretty much it summarizes my problem here:
Double check - does it ever make sense to have internal viewmodel class?
I have controls.DLL and I'd like to keep this custom control bindings and viewmodel's internal. However, this doesn't seem to be possible.
How do you get around that? The only way I see it - don't use bindings..
Why do you have a view model for a custom control? I assume you're assigning the view model object to the DataContext property, but this is almost always a mistake: the DataContext should be available to consumers to use and abuse as they please. Stated another way, what happens if a consumer of your custom control explicitly sets the DataContext? It sounds like your control will stop working and throw a bunch of xaml binding errors.
A custom control is inherently lookless. There is no model or view model, just a view. That view is the .cs file. You supply a default look via your themes/generic.xaml file, but consumers should be able to supply their own template. If you're tying them to a view model, they also need to know how to create a view model instance and all of its dependencies. You've just created highly coupled code. DI containers can loosen the coupling, but that just downgrades the relationship between classes from "coupled" to "related". I say, why do consumers even need to know that information?
A better approach is to provide all of the properties for your control as dependency properties. Then your generic.xaml can provide a control template that uses the more efficient TemplateBinding to bind properties/objects to your control. If you need to populate these dependency properties from a business object, expose another dependency property of type IBusinessObject and set the derived values in that object's PropertyMetaData changed handler. If your IBusinessObject type contains a property which is yet another class which implements INotifyPropertyChanged, you should probably (1) rethink your object graph or (2) create a Bnding object in code using the subclass.
I think following all of the above advice will eliminate the problem about which you're concerned plus the other problems as well. Leave the view models to the UserControls. And yes, this is why custom controls are a MASSIVE headache. Doing them right is fairly involved.
Try protected internal. I suppose this should work. Although I don't think its good idea to have the ViewModel not public at all, cause one of the purposes of it is to be able to define several Views against the same ViewModel, which may come from different assemblies.

What's with empty code-behinds?

I understand the benefit to unit testing of preferring the view-model over the code-behind. However, I cannot understand the obsession with achieving completely empty code-behinds. At compile time, the code behind and the XAML are combined, so they are actually the same thing. I, to, love using XAML due to its declarative nature which is very cool. But is there actually any practical reason for insisting that all view-related code be XAML rather than C#?
There are also some benefits in taking advantage of what Blend can do at design-time with XAML but that's really more of a XAML vs (the same code) in code-behind argument. For the no code-behind argument as it relates to MVVM the real goal, as you've pointed out, is to get code moved into classes like ViewModels that can be tested and reused. As with many things, this often gets taken to the extreme and people end up insisting that there never be any code-behind when what is really needed is to have no business logic in code-behind, disregarding that there is also often UI logic too.
XAML is very rich and allows you to do a lot declaratively but there are still UI specific things (i.e. event handlers, some animation handling) that can't be done without using some code. You can usually manage to move this code to some place other than the code-behind by using things like custom controls, attached properties, etc. but if you're not getting any reuse benefits out of doing that it's probably just better to use the code-behind to do that UI logic instead.
Patterns like MVVM are general guiding principles, not a set of strict rules to be obsessively adhered to - those are called programming languages. :)
On good reason is that with WPF and XAML, Microsoft aim to keep separated the graphical and coding jobs. In this way, developer and UI designer can work easilly.
It's all about testability. It's hard (nigh impossible) to unit test your code behinds. With MVVM, you can create test harnesses that fully test your Model and ViewModel.
That being said, I'm a fan of being pragmatic. Some UI events are a bear to set up using Commands, and for those, I'll sometimes drop down into the codebehind.
The view model is the code-behind for the XAML. At least, that's how I think of it. And it's a code-behind file that can be tested without the XAML.
On the other hand, as Ben Johnson might have put it, no man but a fool ever implemented drag and drop in the view model.

Good practice or bad practice

i am new to WPF and i have one question(the first one actually, more to come)
Is it better to add some logic, for example the bindings for the window, in xaml or in the code behind.
If you can put it in XAML, it's generally better to do that than be wiring up stuff in your codebehind.
For one thing, this lets you use tools like Expression Blend more effectively, since you have more stuff available at design time. It also further shifts view logic into the view itself, and helps you stay away from stuffing view-based code in your viewmodels or controllers.
Most people wouldn't consider a binding to be logic. Bindings should generally go in xaml. It is a good idea to put logic in a separate ViewModel class which you bind to.
It's kind of a religious debate right now. With an MVVM approach, you can essentially get away with the only code in your codebehind being the creation of your ViewModel and its assignment to your DataContext.
Even all of your event handling can be managed in your ViewModel using UI Commands.

Should your ViewModel expose XAML elements as properties or not?

Over at the StackOverflow question How can WPF Converters be used in an MVVM pattern? I've learned that Value Converters should not be used in the MVVM pattern since the functionality of a Value Converter should be handled by the ViewModel itself.
This makes sense.
But I remember reading that you should not expose XAML elements to the View, but instead expose only collections of data which the View then binds and displays using DataTemplates.
However, converters seem quite powerful (e.g. as they are used in the MVVM Template demo, see the "Messenger Sample" after unpacking it) in that they can convert objects to objects, e.g. Message objects to FlowDocument objects, or Customer objects into Visibility objects, or custom Status objects into Images, etc.
So if a ViewModel is going to take on the functionality of a Value Converter, it is going to have to expose XAML elements and properties such as StackPanel, Visibility, Color, FlowDocument, etc., right?
Does anyone see any reason why a ViewModel should not expose these rich XAML objects as Value Converters do?
Because then that limits the ViewModel to be used only with a specific visual representation.
Once you have the ViewModel emitting XAML, it puts design content into a developer's domain.
This means that the designer using Expression Blend cannot edit design assets - and the designer/developer workflow is broken.
Keeping the XAML on the page and using Value converters with data templating keeps the design separated from the code.
When your ViewModel exposes specific XAML it also limits that ViewModel to be used only in that specific instance and makes it less reusable.
Don't forget that you can use DataTemplates too. I can see some sense in keeping ValueConverters out of MVVM, but DataTemplates are all about transforming objects into GUI.
Your ViewModel can expose other objects (e.g. nested ViewModels) to the GUI, and the GUI can use <DataTemplate DataType="{x:Type SubViewModel}">... to map those objects to GUI.
Does anyone see any reason why a ViewModel should not expose these rich XAML objects as Value Converters do?
Absolutely, because it undermines all the goals of MVVM:
You're no longer unit testable, at least not easily.
You no longer have separation between logic (view model) and presentation (view). Thus, designers and developers cannot easily collaborate.
Code maintenance is more difficult because you've mixed the concerns together.
If I saw a view model returning a view, I wouldn't even classify it as MVVM.
I think one idea of mvvm/mvc/mvp etc. is to isolate the GUI code to one file/class.
If you do this can you change to some other UI without rewriting the other objects?
I think if you're passing around WPF specific objects the answer is no.
It's a value judgment you'll have to make for your self.
There is no absolute 100% rule that works for this or many other concepts when you discuss them without the perspective of why the community's mind has shifted as it has in this direction. There is no 'assumed' truth or science in 'conventional wisdom' regardless of how new or compelling it is at the time.
In other words - just do the best with your team as if your good, your already getting pulled down far more in human concerns than anything as real as this.

Is Dependency Injection possible with a WPF application?

I want to start using dependency injection in my WPF application, largely for better unit testability. My app is mostly constructed along the M-V-VM pattern.
I'm looking at Autofac for my IoC container, but I don't think that matters too much for this discussion.
Injecting a service into the start window seems straightforward, as I can create the container and resolve from it in App.xaml.cs.
What I'm struggling with is how I can DI ViewModels and Services into User Controls? The user controls are instantiated via XAML markup, so there's no opportunity to Resolve() them.
The best I can think of is to place the container in a Singleton, and have the user controls resolve their ViewModels from the global container. This feels like a half-way solution, at best, as it still required my components to have a dependency on a ServiceLocator.
Is full IoC possible with WPF?
[edit] - Prism has been suggested, but even evaluating Prism seems like a big investment. I'm hoping for something smaller.
[edit] here's a code fragment where I'm stopped
//setup IoC container (in app.xaml.cs)
var builder = new ContainerBuilder();
builder.Register<NewsSource>().As<INewsSource>();
builder.Register<AViewModel>().FactoryScoped();
var container = builder.Build();
// in user control ctor -
// this doesn't work, where do I get the container from
VM = container.Resolve<AViewModel>();
// in app.xaml.cs
// this compiles, but I can't use this uc,
//as the one I want in created via xaml in the primary window
SomeUserControl uc = new SomeUserControl();
uc.VM = container.Resolve<AViewModel>();
It's actually very easy to do. We have examples of this in Prism as jedidja mentioned. You can either have the ViewModel get injected with the View or the View get injected with the ViewModel. In the Prism StockTraderRI, you will see that we inject the View into the ViewModel. Essentially, what happens is that the View (and View interface) has a Model property. That property is implemented in the code-behind to set the DataContext to the value, for example: this.DataContext = value;. In the constructor of the ViewModel, the View gets injected. It then sets View.Model = this; which will pass itself as the DataContext.
You can also easily do the reverse and have the ViewModel injected into the View. I actually prefer this because it means that the ViewModel no longer has any back reference to the view at all. This means when unit-testing the ViewModel, you don't have a view to even Mock. Additionally, it makes the code cleaner, in that in the constructor of the View, it simply sets the DataContext to the ViewModel that was injected.
I talk a bit more about this in the video recording of the Separated Presentation Patterns talk that Jeremy Miller and I gave at Kaizenconf. The first part of which can be found here https://vimeo.com/2189854.
I think you've hit on the issue. The controls need to be injected into their parent rather than created declaratively through XAML.
For DI to work, a DI container should create the class that is accepting dependencies. This means that the parent will not have any instances of the child controls at design time and look something like a shell in the designer. This is probably the recommended approach.
The other "alternative" is to have a global static container called from the control's constructor, or something similar. There is a common pattern in which two constructors are declared, one with a parameter list for constructor injection and the other without parameters that delegates:
// For WPF
public Foo() : this(Global.Container.Resolve<IBar>()) {}
// For the rest of the world
public Foo(IBar bar) { .. }
I would almost call this an antipattern but for the fact that some frameworks leave no other choice.
I'm not even half an expert in WPF, so I'm expecting a healthy serving of downmod here :) but hope this helps. The Autofac group (linked from the homepage) might be another place to ask this question. The Prism or MEF sample apps (which include some WPF examples) should give you an idea of what is possible.
We are experiencing a similar issue. We are looking forward for a solution that will provide Design time support under Expression Blend 2.0 (Strong Type). Plus we are looking forward for a solution to have some Mock+Auto-Generated data sample available under Expression Blend.
Of course, we are looking also to have all those thing work using an IOC pattern.
Paul Stovell as an interesting article to start with:
http://www.paulstovell.com/blog/wpf-dependency-injection-in-xaml
So I try a couple thing to add more valuable design time support for Binding and mocking object at Design time, right now I’m having most of my problem related to get a strong typed connection made between the View (code) to the ModelView(Xaml), I tried a couple scenario:
Solution 1 : Using Generic to create the View
public class MyDotNetcomponent<T> : SomeDotNetcomponent
{
// Inversion of Control Loader…
// Next step add the Inversion of control manager plus
// some MockObject feature to work under design time
public T View {Get;}
}
This solution does not work since Blend does not support Generic inside is design surface but Xaml do have some, well work at runtime but not at design;
Solution 2: ObjectDataProvider
<ObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
<!-- Work in Blend -->
<!—- IOC Issue: we need to use a concrete type and/or static Method there no way to achive a load on demande feature in a easy way -->
Solution 3: Inherit ObjectDataProvider
<CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
<!-- Cannot inherit from ObjectDataProvider to achive the right behavior everything is private-->
Solution 4: Create a mock ObjectDataProvider from scratch to the job
<CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView }" />
<!-- Not working in Blend, quite obvious-->
Solution 5: Create a Markup Extension (Paul Stovell)
<CWM:ServiceMarkup MetaView="{x:Type CP:IFooView}"/>
<!-- Not working in Blend -->
Just to clear one point. When I said “not working in blend”, I mean that the Binding dialog is not usable and the designer needs to handwrite the XAML by itself.
Our next step will probably be to take the time to evaluate the ability to create a plug-in for Expression Blend.
Yes, we do it all the time. You can "inject" your ViewModel into the DataContext of the control.
I actually find WPF being even easier to use with DI. Even the dependency objects and properties work with it seamlessly.
You should take a look at Caliburn - it's a simple WPF/Silverlight MVC framework with support for full DI. It looks really cool and it lets you use any IoC container you want. There are a couple of examples on the documentation wiki
Glen Block (see above) mentions that a common approach is to design your MVVM solution to use the DataContext as the place where you can "resolve" your View Model in the View. Then you can use design extensions from expression blend 2008 (note that you don't need to be using the expression blend design tools to take advantage of this). For example:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MyViewModelMock, IsDesignTimeCreatable=True}"
In your view you can have a property getter that casts your DataContext to the type that you expect (just to make it easier to consume in the code-behind).
private IMyViewModel ViewModel { get { return (IMyViewModel) DataContext; } }
Don't forget to use an interface so that your views are easier to test, or to help you inject different runtime implementations.
In general, you should not be resolving things from the container all over the place in your solution. It is actually considered bad practice to pass your container around in every constructor, or to make it globally accessible. (You should look up discussions of why "Service Locator" strategies constitute an "Anti-Pattern").
Create a public View constructor with explicit dependencies that the container (e.g. Prism Unity or MEF) can resolve.
If necessary, you could also create an internal default constructor to create a mock of your view model (or a real one for that matter). This protects against inadvertent use of this "design constructor" externally (in your "Shell" or wherever). Your test projects can also use such constructors using the "InternalsVisibleToAttribute" in "AssemblyInfo". But of course, that usually isn't necessary since you can inject your mocks using the full dependency constructors anyway, and because the majority of your tests should be focusing on the ViewModel in the first place. Any code in the View should ideally be quite trivial. (If your View requires a lot of testing, then you might want to ask yourself why!)
Glen also mentions that you can inject Views into View Models, or View Models into Views. I much prefer the latter because there are perfectly good techniques for decoupling everything (use of Declarative Binding, Commanding, Event Aggregation, Mediator patterns, etc.). The View Model is where all the heavy lifting will be done to orchestrate core business logic. If all of the necessary "binding" points are provided by the View Model, it really shouldn't need to know ANYTHING about the View (which can mostly be wired up to it declaratively in the XAML).
If we make the View Model agnostic to the source of user-interaction, that makes it much easier to test (preferably first). And it also means that you can easily plug in ANY view (WPF, Silverlight, ASP.NET, Console, etc.). In fact, to ensure that appropriate decoupling has been achieved, we can ask ourselves if a "MVM" (Model-ViewModel) architecture could work in the context of, say, a Workflow service. When you stop to think about it, most of your unit tests will probably be designed on that premise.
I think You have to Decide on View First or Viewmodel First then as given the other answer it Can be decide.. There are several open source framework does it same . I use Caliburn where ViewModel first is taken and its really good approach
I wrote an very light framework where a ViewModel is resolved at runtime by using a IoC (Unity) as a markup extension.
The framework allows for writing XAML without a code behind but still lets you have routed commands, data binding, and event handlers.
In any case, I don't think you need the loose XAML in your case, but if you look at the code (http://xtrememvvm.codeplex.com), it might turn out that you can use some of the code to solve your own issues with injecting View Models and Services.

Resources