DataGrid Tips & Tricks: Column Selection

V1 of the DataGrid does not come with built-in column selection functionality, but this feature is easy to implement in your own application. Pasting the styles below into your DataGrid's Resources will add a button to the Column Header which allows the end user to select the column. The two methods below contain the logic for selecting all of the cells in a column when the header is clicked and should be pasted into the code-behind (remember to replace "myDataGrid" with the name of your DataGrid control).

         <!--
          COLUMN SELECTION:
          These resources add a button to the column header that will select
          all of the cells in that column.
        -->
        <Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
          <Setter Property="Width" Value="8"/>
          <Setter Property="Background" Value="Transparent"/>
          <Setter Property="Cursor" Value="SizeWE"/>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type Thumb}">
                <Border Padding="{TemplateBinding Padding}"
                    Background="{TemplateBinding Background}"/>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
        
        <Style x:Key="SelectColumnButtonStyle" TargetType="{x:Type Button}">
          <Setter Property="VerticalAlignment" Value="Bottom" />
          <Setter Property="Height" Value="10" />
          <Setter Property="ClickMode" Value="Press" />
          <Setter Property="Cursor" Value="ScrollS" />
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type Button}">
                <Border Background="Transparent" />
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
        
        <Style x:Key="{x:Type dg:DataGridColumnHeader}" TargetType="{x:Type dg:DataGridColumnHeader}">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type dg:DataGridColumnHeader}">
                <Grid>
                  <dg:DataGridHeaderBorder SortDirection="{TemplateBinding SortDirection}"
                                     IsHovered="{TemplateBinding IsMouseOver}"
                                     IsPressed="{TemplateBinding IsPressed}"
                                     IsClickable="{TemplateBinding CanUserSort}"
                                     Background="{TemplateBinding Background}"
                                     BorderBrush="{TemplateBinding BorderBrush}"
                                     BorderThickness="{TemplateBinding BorderThickness}"
                                     Padding ="{TemplateBinding Padding}">
                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
                  </dg:DataGridHeaderBorder>

                  <Thumb x:Name="PART_LeftHeaderGripper"
                   HorizontalAlignment="Left"
                   Style="{StaticResource ColumnHeaderGripperStyle}"/>
                  <Thumb x:Name="PART_RightHeaderGripper"
                   HorizontalAlignment="Right"
                   Style="{StaticResource ColumnHeaderGripperStyle}"/>
                  <Button x:Name="SelectColumnButton" 
                          Style="{StaticResource SelectColumnButtonStyle}"
                          Click="SelectColumn"/>
                </Grid>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>

        //
        // COLUMN SELECTION:
        // These next two functions respond to the button click and select
        // the cells in the column.
        //

        private void SelectColumn(object sender, RoutedEventArgs e)
        {
            if (myDataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
            {
                DataGridColumnHeader header = FindVisualParent<DataGridColumnHeader>((Button)sender);
                if (header != null)
                {
                    myDataGrid.SelectedCells.Clear();

                    DataGridColumn column = header.Column;
                    for (int i = 0; i < myDataGrid.Items.Count; i++)
                    {
                        myDataGrid.SelectedCells.Add(new DataGridCellInfo(myDataGrid.Items[i], column));
                    }
                }
            }
        }

        private static T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            UIElement parent = element;
            while (parent != null)
            {
                T correctlyTyped = parent as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }

                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }

            return null;
        }

Last edited Nov 6, 2008 at 6:19 PM by VamseeP, version 7

Comments

RredCat Feb 12, 2009 at 11:28 AM 
2 r honey:
It works. You need to set .SelectionUnit = DataGridSelectionUnit.CellOrRowHeader | DataGridSelectionUnit.Cell (not DataGridSelectionUnit.FullRow) only.

r_honey Nov 5, 2008 at 1:50 PM 
I pasted the code as is for my grid. The cursor changes when I hover over a Column Header but the column is NOT selected when I click it.
What should I do??