Inter-Column communication in a WPF GridView
Loads of times I have been asked in forums, how do I make a GridViewColumn communicate with another in WPF. A common use case is that you have a checkbox in Column1 and you want that when the checkbox is checked something happens in Columnx.
The first obvious answer is make a property in your business object that can reflect that change. Yet some times this is strictly UI and you don’t want to clutter your business object with UI code.
One solution could be to use the power of DataBinding. Lets start by explaining in very high level, how a GridView works. So a GridView is simply a Logical entity. To make it sound more familiar we can say that a GridViewColumn is like Grid ColumnDefinition / RowDefinition. It’s an entity that will effect how the parent (in our case the ListView) will look. A GridView will construct a GridViewHeaderRowPresenter and a GridViewRowPresenter that will construct the header of the ListView and the ListView rows. Because the GridView does this, we can do a trick with databinding that will enable us to make Inter-Column communication possible.
Basically the idea is to bind the CheckBox’s IsChecked property to the Tag property of it’s GridViewRowPresenter with a OneWayToSource binding. This will make sure that when the user check/unchecks the Checkbox the IsChecked state is stored in the GridViewRowPresenter. something like this
1: <GridViewColumn Header="checkbox here" Width="100">
2: <GridViewColumn.CellTemplate>
3: <DataTemplate>
4: <CheckBox IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type GridViewRowPresenter}}, Path=Tag, Mode=OneWayToSource}"/>
5: </DataTemplate>
6: </GridViewColumn.CellTemplate>
7: </GridViewColumn>
Now that we have that in place other columns can easily become aware of the state changes by doing a DataTrigger on the GridViewRowPresenter like so
1: <GridViewColumn Header="text here" Width="100">
2: <GridViewColumn.CellTemplate>
3: <DataTemplate>
4: <TextBlock Text="{Binding}" Foreground="Red" x:Name="text"/>
5: <DataTemplate.Triggers>
6: <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type GridViewRowPresenter}}, Path=Tag}" Value="True">
7: <Setter TargetName="text" Property="Foreground" Value="Green"/>
8: </DataTrigger>
9: </DataTemplate.Triggers>
10: </DataTemplate>
11: </GridViewColumn.CellTemplate>
12: </GridViewColumn>
and that’s basically it…
Thank you WPF!!!! We love you





[...] Inter-Column Communication in a WPF GridView (Marlon Grech) [...]
Pingback by Dew Drop - July 1, 2008 | Alvin Ashcraft's Morning Dew | July 1, 2008 |
really very gud for beginers…..thanks alot
I have a menuitem that binds a commandparameter
CommandParameter=”{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget}”
PlacementTarget puts me at a grid that forms the datatemplate of my GridViewColumn.
what would be the binding expression to continue this up to finally bind GridViewColumn to the commandparameter?
is that even possible?
thanks,
-lm
Hey there,
Unfortunately you cannot do this. A GridViewColumn will not be in the VisualTree becuase it is not actually a UI element thus it is useless to do RelativeSourceBinding to walk up the tree because the GridViewColumn will not be there. Think of GridViewColumn just like a RowDefinition. You type it in XAML but it is not in the UI tree.
I am sure you can find a workaround… if you need anymore help let me know
Regards
i provided a solution to my problem on http://www.codeplex.com/wpf/Thread/View.aspx?ThreadId=39537
someone else asked the same question.
I just wonder why i couldn’t get to the content presenter from GridViewHeaderRowPresenter ??
o well problem solved for now.
thanks,
yes wpf is very nice interms of UI when compared to WinForms. i like the style seperation from controls like css