DataGridCheckBoxColumn Styling & Binding Issue

Oct 1, 2010 at 9:40 AM

Hi there,

I am trying to style a grid of mine so that an image is being displayed depending of the value of the DataGridCheckBoxColumn. The default is to display a checkbox, but I want to replace the checkbox with a red or green image.

I have search around but wasn't too successful in find samples. If I do find something, I will post it here.

Thanks in advance.

Oct 1, 2010 at 2:06 PM

You could create a new style/controltemplate for your checkbox. Here is an example:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid>  
    <Grid.Resources>
      <Style x:Key="ImageCheckBox" TargetType="{x:Type CheckBox}">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
              <DockPanel>
                <Image x:Name="img" DockPanel.Dock="Left" 
                       Source="Image1.jpg"
                       VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                       Width="50" Height="50"/>
                <ContentPresenter Margin="{TemplateBinding Padding}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                  RecognizesAccessKey="True"
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
              </DockPanel>
            <ControlTemplate.Triggers>
              <Trigger Property="IsChecked" Value="True">
                <Setter TargetName="img" Property="Source" Value="Image2.jpg"/>
              </Trigger>
            </ControlTemplate.Triggers>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </Grid.Resources>
    
    <CheckBox Content="CONTENT" VerticalContentAlignment="Center"
              Style="{StaticResource ImageCheckBox}"/>
  </Grid>
</Page>

Regards,

Marcel

Oct 1, 2010 at 2:34 PM
Edited Oct 1, 2010 at 10:47 PM

Thanks that worked great!

Oct 5, 2010 at 1:54 PM

what will be the size of Image2.jpg?

or we can replace it with any other image?

Oct 5, 2010 at 2:03 PM

You can replace it by any image you want. If you look at the <Image /> in the DockPanel you will see that the size of the image is set there; that will determine the size of the image in the column.

Nov 12, 2010 at 8:31 PM

Thanks for this, it works great to a certain extent but with regards to Binding it doesn't work that well...

How do I get it to change the property it is bound to? At the moment I have to perform some seriously weird click behaviour which makes the actual textbox show before the value is actually recorded. By just clicking on the checkbox and the a button to record everything that changed in the grid does not work.

I can't expect of my users to click more than once just to get a simple thing like this to happen. And to be to learn how to click would be impossible as I can't even explain now how you should click to get it working.

Any ideas?

Nov 15, 2010 at 1:54 PM

Your problem might be that the DataGrid has a pretty strict separation between view-mode and edit-mode. You first have to select the cell, then to click again to enter edit mode... I found this tip that might help to save you a click. Maybe it can help you in your scenario.

This is my new attempt and it seems to work pretty well:

<Window x:Class="WpfImageCheckBoxInDataGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid AutoGenerateColumns="False" Margin="12" Name="dataGrid1" 
                  ItemsSource="{Binding Employees}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
                <DataGridCheckBoxColumn Binding="{Binding IsFulltime}" Header="Fulltime"/>
                <DataGridCheckBoxColumn Binding="{Binding IsHappy}" Header="Happy"/>
                <DataGridTemplateColumn Header="Happy as image">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <Image x:Name="img" DockPanel.Dock="Left" 
                                       Source="/WpfImageCheckBoxInDataGridTest;component/Blue_smiley_crying.png"
                                       VerticalAlignment="Center"
                                       Width="20" Height="20"/>
                                <!-- Almost invisible checkbox-->
                                <CheckBox Opacity="0.001" IsChecked="{Binding IsHappy, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                            </Grid>
                            <DataTemplate.Triggers>
                                <DataTrigger Binding="{Binding IsHappy}" Value="True">
                                    <Setter TargetName="img" Property="Source" Value="/WpfImageCheckBoxInDataGridTest;component/Blue_smiley_happy.png"/>
                                </DataTrigger>
                            </DataTemplate.Triggers>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

There's still a small issue with the 'new item' row: you'll have to set another property of that row first.

You can download my testproject (WPF4) from here: https://cid-027cdb908d14e584.office.live.com/self.aspx/WPFSamples/WpfImageCheckBoxInDataGridTest.zip

Marcel

Nov 17, 2010 at 3:56 PM

Thanks! I will give this suggestion a try but I did the following which solved the problem:
Binding="{Binding NotificationSMS, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

Setting the UPdateSourceTrigger to PropertyChanged seemed to work.