views:

1213

answers:

3

I am trying to use the MVVM pattern to write a WPF application. I am using WPF data grid (from the toolkit) which lacks the autofiltering feature. So I want to implement it. I've added a context menu to the column header template, it has MenuItem called "Filter" which should actually call the filtering method.

So I've set a MenuItem's command to be the appropriate DelegateCommand which goes to the ViewModel. The problem is that I need to pass the information about the actual column that has been right-clicked! If I wasn't using MVVM, I would implement an event handler which would receive a "sender" argument (the MenuItem), then I would find its parent (the ContextMenu), then its parent would give me the column. But how can I achieve the same thing here? How can I pass the sender to my command? Can this be done using ComandParameter?

I really don't want to use additional complicated patterns to achieve such a simple task. After all, MVVM should simplify the development and not vice versa...

+1  A: 

Can you pass the Column header value as a Command Parameter and use that to get the Column details at the ViewModel?

Jobi Joy
How do I do that? Something like <MenuItem CommandParameter="{RelativeSource AccessorType=DataGridColumnHeader, Path=Header}"? And also, if I am using the MVVM toolkit from the codeplex, how can I get the CommandParameter in the ViewModel? Their DelegateCommand doesn't pass parameters...
Dmitry Perets
Just a DataContext binding will do the trick <MenuItem CommandParameter="{Binding}" .../>
Jobi Joy
A: 

You could try some relative source magic, but it might be easier on you if you can have a different ViewModel that you bind to for each header, like HeaderViewModelItem. From there you'd just be firing a DelegateCommand in your HeaderViewModelItem, rather on your larger viewmodel.

I've used this model with pretty good success. Gets around a little bit of databinding dance.

Anderson Imes
A: 

If you want to pass something into the command parameter it is important to note that a context menu is on its own visual tree. Luckily it still inherits the DataContext from its parent, so something like

<MenuItem CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=DataContext}" />

should get you the GridViewColumnHeader, or at least something in the visual tree of it.

Bryce Kahle
The default Binding is always DataContext,<MenuItem CommandParameter="{Binding}" .../> is enough since DataContext will get inherited to the MenuItem also.
Jobi Joy
That depends on how the MenuItems are generated. If they are generated via a Binding themselves, they would not have the same DataContext as the parent.
Bryce Kahle