Search code examples
wpfxamlwpfdatagrid

How to get column reorder working in datagrid


I have created a datagrid with a little customization. The last column header is made up of the usual textblock plus a stackpanel under it with rotated text.

In order to make it look better I made the first 6 columns 25 in height with vertical alignment at the bottom, otherwise they would have stretched to the top.

enter image description here

My second image shows that I can reorder the last column. enter image description here

However I can not reorder any of the first six.

In the next pics (Left) I removed the vertical alignment altogether making it sit in the center by default, (Right) I set the vertical alignment to the Top. enter image description here

As you can see there must be another level of component, you cannot just alter the DataGridColumnHeader style and expect it to be reordered via dragging.

Questions:

  • What do I need to add to my style to bring the dragability down to sit with the lower DataGridColumnHeaders at the bottom, as in the first image?
  • How do I find this constraint? Can I iterate through the elements of the headers listing them out somehow?
  • And lastly the transparent floating dragged image of the column is aligned to the top I would like that brought down to sit at the bottom with the actual header labels, how to do?

Here is my XAML code:

<Window x:Class="DGTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="500">

    <Window.Resources>
        <Style TargetType="DataGridColumnHeader">
            <Setter Property="Background" Value="Transparent"/>
        </Style>
        <Style x:Key="ColumnHeaderStyle" TargetType="DataGridColumnHeader">
            <Setter Property="Height" Value="25" />
            <Setter Property="VerticalAlignment" Value="Bottom"/>
        </Style>

    </Window.Resources>

    <Grid Name="gridUsers" Background="Transparent">
        <DockPanel Background="Transparent">
            <DataGrid Background="Transparent" CanUserReorderColumns="True" AutoGenerateColumns="False" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="ID" CanUserReorder="True" IsReadOnly="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" Binding="{Binding Path=User_ID}"/>
                    <DataGridTextColumn Header="Name" CanUserReorder="True" CanUserSort="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" Binding="{Binding Path=Name}"/>
                    <DataGridTextColumn Header="Username" CanUserReorder="True" CanUserSort="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" Binding="{Binding Path=Username}"/>
                    <DataGridTextColumn Header="Job Title" CanUserReorder="True" CanUserSort="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" Binding="{Binding Path=Job_Title}"/>
                    <DataGridTextColumn Header="Department" CanUserReorder="True" CanUserSort="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" Binding="{Binding Path=Department}"/>
                    <DataGridTextColumn Header="Company" CanUserReorder="True" CanUserSort="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" Binding="{Binding Path=Company}"/>
                    <DataGridTemplateColumn CanUserReorder="True" CanUserSort="False" >
                        <DataGridTemplateColumn.Header>
                            <StackPanel Orientation="Vertical" Background="Transparent" HorizontalAlignment="Center">
                                <Label Background="AliceBlue" HorizontalAlignment="Stretch" Height="25" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" >
                                    Access
                                </Label>
                                <StackPanel Orientation="Horizontal" Background="Transparent" CanVerticallyScroll="False" CanHorizontallyScroll="False">
                                    <TextBlock Text="Read" Width="80" Margin="20,1,0,1" >
                                        <TextBlock.LayoutTransform>
                                          <RotateTransform Angle="-60"/>
                                        </TextBlock.LayoutTransform>
                                    </TextBlock>
                                    <TextBlock Text="Write" Width="80" Margin="-15,1,0,1" >
                                        <TextBlock.LayoutTransform>
                                          <RotateTransform Angle="-60"/>
                                        </TextBlock.LayoutTransform>
                                    </TextBlock>
                                    <TextBlock Text="Administrator" Width="80" Margin="-15,1,0,1" >
                                        <TextBlock.LayoutTransform>
                                          <RotateTransform Angle="-60"/>
                                        </TextBlock.LayoutTransform>
                                    </TextBlock>
                                </StackPanel>
                            </StackPanel>
                        </DataGridTemplateColumn.Header>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
        </DockPanel>
    </Grid>
</Window>

Solution

  • I tried to fulfill your requirement with the following changes. Change the ColumnHeaderStyle as given below. I just given raw style of column headers with the following changes. Change that as per your application needs.

      <Style TargetType="DataGridColumnHeader">
            <Setter Property="Background" Value="Transparent"/>
        </Style>
    
     <Style x:Key="ColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="VerticalContentAlignment" Value="Bottom"/>
            <Setter Property="VerticalAlignment" Value="Stretch"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="DataGridColumnHeader">
                        <Grid>
                        <Border Background="Gray" VerticalAlignment="Bottom" Margin="1">
                            <ContentPresenter Content="{TemplateBinding Content}" Margin="5" VerticalAlignment="Bottom"/>
                        </Border>
                        <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left">
                            <Thumb.Style>
                                <Style 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 Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </Thumb.Style>
                        </Thumb>
                        <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right">
                            <Thumb.Style>
                                <Style 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 Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </Thumb.Style>
                        </Thumb>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    Also set the DragIndicatorStyle of all columns as given below.

     <Style x:Key="DragIndicatorStyle" TargetType="Control">
            <Setter Property="Height" Value="75"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Margin" Value="0,-25,0,0"/>
            <Setter Property="VerticalAlignment" Value="Bottom"/>
            <Setter Property="VerticalContentAlignment" Value="Bottom"/>                   
        </Style>