Apply style to column

Sep 9, 2008 at 11:04 PM
In the thread: http://www.codeplex.com/wpf/Thread/View.aspx?ThreadId=34502 I was given some tips on customizing the header of all columns in the DataGrid. The help was great and I've been able to get it working.

Now I'm trying to style a column, based upon whether a checkbox in the column header is checked. If it is checked, I want things displayed as normal, if not checked, I want to change the background color (and possibly a few other properties) for that entire column. I'm thinking I should be able to switch the column style between two predefined styles using a trigger. Unfortunately, there doesn't seem to be a ColumnStyle property to set, so I'm a little confused as to how to proceed.

Once again, any help is appreciated.

Thank you.
Coordinator
Sep 10, 2008 at 6:25 PM
What is a little tricky about this is accessing cells of a column directly from a column header.  What you do have access to from a cell or a columnHeader is the Column itself.  With that you have access to base properties of Column as well as the CellStyle.  Here is an example of using a checkbox in a column header to set the background of the cells in that column.  I don't show the converter but all I'm doing is returning a specific CellStyle based on the IsChecked property of the CheckBox in the header.

<

 

Style x:Key="CellStyle1" TargetType="{x:Type dg:DataGridCell}">
    <Setter Property="Background" Value="White" />
</Style>

 

 

 

<Style x:Key="CellStyle2" TargetType="{x:Type dg:DataGridCell}">
    <Setter Property="Background" Value="Red" />
</Style>

 

 

 

<local:CellBackgroundConverter x:Key="CellBackgroundConverter" CellStyle1="{StaticResource defaultCellStyle}" CellStyle2="{StaticResource CellStyle2}"/>

<

 

dg:DataGridTextColumn x:Name="FirstNameColumn"Header="First Name" DataFieldBinding="{Binding Path=FirstName}" >
    <dg:DataGridTextColumn.HeaderTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type dg:DataGridColumnHeader}}, 
                                                                         Path=Column.CellStyle, 
                                                                         Mode=OneWayToSource, 
                                                                         Converter={StaticResource CellBackgroundConverter}}" />
        </DataTemplate>
    </dg:DataGridTextColumn.HeaderTemplate>
</dg:DataGridTextColumn>

 

Sep 11, 2008 at 3:21 PM
Thanks. This does work, but I'm wondering if there is a way to do this with a trigger on the checkbox instead. Obviously the difficulty would be in figuring out what to target. The reason I'm asking this is because I'd really rather have the checkbox bound to a boolean property in my data object. I think ideally, there'd be either a style trigger or data trigger that would change the column's cell style, while the binding would handle the data. Any thoughts?
Coordinator
Sep 11, 2008 at 8:51 PM
I don't really follow your scenario.  You want to put a checkbox on one column header or all column headers?  From your inital question it looks like you want it to be possibly on all columns.  If the checkbox is checked then you want all the cells in that column to change background color right.  What I don't really follow is how you want to map a boolean property on the data item to each column.  If you do that, then all the columns will change background color, not just the cells in the column that you just checked.
Sep 11, 2008 at 9:16 PM
I think an image will clear things up:

http://brian.vallelunga.com/files/importer-header.png

All columns are auto-generated. Each column header has a checkbox in it. This checkbox should be bound to a property on an object that contains some metadata about the column being displayed. (This is what my other thread was about -- binding the checkbox to a property on a custom DataColumn). What I would like is that when I check/uncheck the checkbox, the bound property is updated and the column's CellStyle is updated.

So while the suggested databinding method works, it means I can't bind the checkbox to the underlying data anymore. My thought would be to then use a trigger (DataTrigger?) so that when the underlying data is changed, the CellStyle for that column's cells is also changed (via the trigger, and not from DataBinding). I'm just not sure how to target the auto-generated column's CellStyle property with a trigger. I really feel like there ought to be a way to do this with WPF without resorting to wiring up event handlers.

I've been reading as much as I can about triggers and binding and haven't found anything beyond very simple examples.

Thanks again,
Brian



Coordinator
Sep 11, 2008 at 11:05 PM
When you say, "I can't bind the checkbox to the underlying data anymore", how were you originally binding to the underlying data?

There is a reason why the column header's DataContext does not work like a DataGridColumn.  While a DataGridColumn will work for all items in the collection, a DataGridColumnHeader does not since there is only one piece of content in the header.  If you were able to bind the header to a property on a data item, which data item in the underlying collection would you expect it to represent?

If you want the header bound to data that is not part of DataGrid's colleciton then that is a little different story.
Sep 12, 2008 at 6:56 AM
> When you say, "I can't bind the checkbox to the underlying data anymore", how were you originally binding to the underlying data?

I wasn't binding the checkbox to any data source originally. Ideally though, I'd like to do that. I was simply stating that if I used the method you suggested above, there'd be no way to also bind the header checkbox to any underlying data.

I'd like to have the header's DataContext set to my custom ImporterDataColumn. My custom column class inherits from DataColumn, which is used in the the DataTable I have. Note that this is not a DataGridColumn, but the ADO.NET DataColumn. This class includes the data properties that correspond to the form elements in the header (Import, CustomHeader, etc). But I can't figure out how to set the DataContext of a header manually to the ImporterDataColumn class I have. Even if I was able to do this, I'm not sure how I would go about changing the column's styles when the value changed (using triggers).
Coordinator
Sep 16, 2008 at 4:15 PM
I just wrote a blog post with example on styling columns based on some of the conditions talked about here.  Hope it helps.

http://blogs.msdn.com/vinsibal/archive/2008/09/16/wpf-datagrid-styling-rows-and-columns-based-on-header-conditions-and-other-properties.aspx