WPF Command binding

WPF Command binding

Old forum URL: forums.lhotka.net/forums/t/6540.aspx


ajj3085 posted on Monday, March 02, 2009

Hi,

I was wondering how people handle common wpf commands, like ApplicationCommands.Print.  Looking at the CslaDataProviderCommandManager, you can see that it tells wpf to enable the Save command if the BO IsSavable.    I'm assuming that putting an IsPrintable property on my BOs isn't the way to go.  Not only does that seem to ask the BO for knowledge it probably should have, you'd have to modify CslaDataProviderCommandManager to hook the bindings in.

So.. what is everyone else doing?

RockfordLhotka replied on Monday, March 02, 2009

I think it depends on who is responsible for printing. Probably not the business object, and thus probably not the CslaDataProvider.

Microsoft has been talking up this ViewModel pattern (Model/View/ViewModel and maybe Controller) idea. The gist of it is that WPF commanding is great, but needs a target. The target shouldn't be the view or the controller or the model, so they invented the ViewModel.

The ViewModel is part of the UI, and basically provides a way to get at the Model, and a way to expose methods for commanding.

In a sense, the CslaDataProvider is a ViewModel - just one that exposes a very defined set of methods for commanding. But conceptually, a ViewModel does exactly what CslaDataProvider does - grants access to the Model (the business object) and supports various commands for the UI.

I have just one quibble with the ViewModel idea: I think the ViewModel is likely to gather business logic, even though it is part of the UI. It is just too darn convenient as a location to do validation-before-save and that sort of thing - so it may lead to really fancy/complex VB3 style coding.

But I guess that's true of anything we come up with - it can be misused...

Anyway, in general terms, you can probably combine the concepts. Use a CslaDataProvider to do the basic CRUD operations, because it supports those. And create a ViewModel or CommandProcessor object to which you can bind your other buttons.

If you have a controller, the controller is really responsible for most of what CslaDataProvider does - you just write the code yourself instead of using a pre-built component. And in that case the ViewModel pattern probably makes more sense overall, and you may just implement all the data provider operations in your controller code.

But if you manage everything purely through XAML, then you may not have a discrete controller. In that case having a data provider plus a command processor may be a better alternative. This is the angle I've been exploring.

In your resources then, you'd have two things:

<..Resources>
  <csla:CslaDataProvider x:Key="MyData" ... />
  <this:PrintHandler x:Key="PrintHandler" 
                              DataContext="{StaticResource MyData}" />
</..Resources>

And then your Print button can use the PrintHandler as a target.

The thing is, nearly any .NET object (with a public default constructor) can be used as a resource like this. It doesn't need anything special really. Though to be a command target the object does need to inherit from UIElement (which is the whole reason CslaDataProviderCommandManager exists).

So your PrintHandler class would just inherit from UIElement and would include the code necessary to implement the Print command - much like CslaDataProviderCommandManager does with its commands.

The DataContext (or you can use the Source model I've been doing for Silverlight) allows PrintHandler to gain access to the business object you want to print.

If you look at the way I use Csla.Wpf.ObjectContext in the 2008 book, you'll see that I use it in a manner very similar to what I'm talking about here. It doesn't support any commands, but does expose a bunch of bindable properties based on the state of the business object.

ajj3085 replied on Tuesday, March 03, 2009

Wow... much more involved than I thought, but it doesn't seem too difficult.  I'll try this approach.. thanks for the detailed answer!

RockfordLhotka replied on Tuesday, March 03, 2009

It isn’t difficult really :)

 

The thing is, that some bit of code has to handle the command. Commanding is only magical at the XAML level, but behind the scenes there’s always a command hander that does some actual work.

 

Btw, you can create your own commands too – you aren’t limited to just those defined by the standard list.

 

Rocky

tmg4340 replied on Tuesday, March 03, 2009

RockfordLhotka:

Microsoft has been talking up this ViewModel pattern (Model/View/ViewModel and maybe Controller) idea. The gist of it is that WPF commanding is great, but needs a target. The target shouldn't be the view or the controller or the model, so they invented the ViewModel.

The ViewModel is part of the UI, and basically provides a way to get at the Model, and a way to expose methods for commanding.

I will admit that I'm still a WPF newbie, not to mention the whole MVC/MVVM concept.  And this certainly isn't a CSLA-specific question.  But I'm curious - why would the Controller not be a good target for a WPF command?  Isn't the point of WPF commands to provide a way for multiple UI elements to fire off the same code?  Since the Controller is designed to handle the user interaction with the view... why wouldn't you target a WPF command at your Controller?  Why the need for a ViewModel?

- Scott

RockfordLhotka replied on Tuesday, March 03, 2009

I don’t know that I can do justice to the MVVM pattern, you should really read the content put out by its proponents.

 

My understanding is that the Controller should be UI-neutral. There’s still this (imo mythical) thought that you can create a Controller that works for Windows, web, WPF and other interface types, so the controller shouldn’t be specific to any UI technology.

 

I think that’s unrealistic, because the typical user experience and UI flow for a smart client and a web client are quite different. Maybe, just maybe, you could share a Controller between a WinForms and WPF and Silverlight UI, but the web is so different they just don’t line up.

 

Anyway, I suspect that’s the rationalization – keep the Controller independent of the specific UI technology – which means it couldn’t be a command target, because then it would have to inherit from UIElement and would be tied directly to WPF.

 

Putting my skepticism aside just a bit – I think you really could envision a Controller that supported both WPF and Silverlight UIs, because they are nearly the same. But the implementation isn’t the same at the moment, so it would be bad to tie the Controller directly to WPF or Silverlight even in this case.

 

The ViewModel provides a layer of abstraction between the View and the Controller (and the Model) that can be safely UI specific. At least that’s my understanding.

 

Rocky

 

tmg4340 replied on Tuesday, March 03, 2009

RockfordLhotka:

I don’t know that I can do justice to the MVVM pattern, you should really read the content put out by its proponents.

Great - more reading to add to my list.  And since MVVM seems to be the "it" way of building WPF apps, I suppose I can't dodge this one...  *sigh*

This is getting a little far afield of Andy's original question, but I wanted to comment that I agree that building the "uber-Controller" to handle any and all UI comers is a pipe dream.  If you could do that, then you wouldn't have different UI constructs - because they'd all work the same.  At that point, it's just transport differences.

Just MHO.  Thanks.

- Scott

SeVa replied on Wednesday, March 04, 2009

The CompositeWPF introduces two new commands that can be routed outside the boundaries of the logical tree and that do not require handling logic in the code behind.
Trying to leverage the CslaDataProvider(CompositePTracker)

Copyright (c) Marimer LLC