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 😀

Download demo Application

Advertisements

WPF: Reducing CPU consumption for animations

Lately I’ve been working on a project at work and the application was performing pretty well. The CPU Usage was below 2% and I was quite happy with it. Then I decided to add a simple animation that continues executing forever… the results 15% CPU consumption … I was amazed at how much CPU was being wasted. Yet I am a stubborn guy and if I want an animation to execute forever, I will do it no matter what….

I started researching and I found out that WPF animations by default try to serve a 60 frames per second… Which is quite a lot!!! After having a chat with my friend ( and role model ) DR.WPF, it was all clear. (Thanks Dr for all the help you give me !!!)

So in order to reduce the frame rate per second (thus reducing CPU usage), all you need to do is to override the property meta data of the Dependency property Timeline.DesiredFrameRateProperty…. So basically all you need is 1 line of code (I usually put this code on startup of the application)

   1: Timeline.DesiredFrameRateProperty.OverrideMetadata(
   2:             typeof(Timeline),
   3:             new FrameworkPropertyMetadata { DefaultValue = 20 }
   4:             );

Yep, that’s it… Amazing but true…. I managed to make an application that was consuming 15% CPU to consume 2% CPU….

With regards to what frame rate should you use, I would leave that to you…. This depends on how smooth you want your animations to perform… Yet for me 20 is working quite fine…

Hope this helps

kick it on DotNetKicks.com