wpfdatagridresizemouseevent

How to get an event when user resize WPF DataGrid column by mouse


How to get an event for column resize invoked by user interaction (mouse left button + mouse move).

I tried SizeChanged event, but it is triggered also when new items are added to the DataGrid (with long text), but this case should not be handled.

<DataGrid.CellStyle>
    <Style TargetType="DataGridCell">
        <EventSetter Event="SizeChanged" Handler="DataGridCell_SizeChanged" />
    </Style>
</DataGrid.CellStyle>

Thanks for any advice.


Solution

  • I used Blend to get the style for DataGrid all the way to DataGridColumnHeader and Thumb (DataGrid > DataGridColumnHeadersPresenter > DataGridColumnHeader > Thumb, ColumnHeaderGripperStyle). Then used Thumb x:Name="PART_RightHeaderGripper" and handled PreviewMouseLeftButtonDown and PreviewMouseMove events.

            <Style x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}" TargetType="{x:Type Button}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Grid>
                                <Rectangle x:Name="Border" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" SnapsToDevicePixels="True"/>
                                <Polygon x:Name="Arrow" Fill="Black" HorizontalAlignment="Right" Margin="8,8,3,3" Opacity="0.15" Points="0,10 10,10 10,0" Stretch="Uniform" VerticalAlignment="Bottom"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Stroke" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Fill" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Visibility" TargetName="Arrow" Value="Collapsed"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
            <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 Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
            <Style x:Key="ThumbStyle1" 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>
            
            <Style x:Key="DataGridColumnHeaderStyle1" TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                            <Grid>
                                <theme:DataGridHeaderBorder Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" IsPressed="{TemplateBinding IsPressed}" IsHovered="{TemplateBinding IsMouseOver}" IsClickable="{TemplateBinding CanUserSort}" Padding="{TemplateBinding Padding}" SortDirection="{TemplateBinding SortDirection}" SeparatorVisibility="{TemplateBinding SeparatorVisibility}" SeparatorBrush="{TemplateBinding SeparatorBrush}">
                                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                </theme:DataGridHeaderBorder>
                            <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ThumbStyle1}" />
                            <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"
                                       PreviewMouseLeftButtonDown="PART_RightHeaderGripper_PreviewMouseLeftButtonDown"
                                       PreviewMouseMove="PART_RightHeaderGripper_PreviewMouseMove"
                                       />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
            <Style x:Key="DataGridColumnHeadersPresenterStyle1" TargetType="{x:Type DataGridColumnHeadersPresenter}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
                            <Grid>
                                <DataGridColumnHeader Style="{DynamicResource DataGridColumnHeaderStyle1}" x:Name="PART_FillerColumnHeader" IsHitTestVisible="False"/>
                                <ItemsPresenter/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
            <Style x:Key="DataGridStyle1" TargetType="{x:Type DataGrid}">
                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="BorderBrush" Value="#FF688CAF"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected"/>
                <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
                <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
                <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGrid}">
                            <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                                <ScrollViewer x:Name="DG_ScrollViewer" Focusable="false">
                                    <ScrollViewer.Template>
                                        <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                            <Grid>
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="Auto"/>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width="Auto"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto"/>
                                                    <RowDefinition Height="*"/>
                                                    <RowDefinition Height="Auto"/>
                                                </Grid.RowDefinitions>
                                                <Button Command="{x:Static DataGrid.SelectAllCommand}" Focusable="false" Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
                                                <DataGridColumnHeadersPresenter Style="{DynamicResource DataGridColumnHeadersPresenterStyle1}" x:Name="PART_ColumnHeadersPresenter" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
                                                <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" Grid.Row="1"/>
                                                <ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Grid.Row="1" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
                                                <Grid Grid.Column="1" Grid.Row="2">
                                                    <Grid.ColumnDefinitions>
                                                        <ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
                                                        <ColumnDefinition Width="*"/>
                                                    </Grid.ColumnDefinitions>
                                                    <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
                                                </Grid>
                                            </Grid>
                                        </ControlTemplate>
                                    </ScrollViewer.Template>
                                    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </ScrollViewer>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsGrouping" Value="true"/>
                            <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                    </MultiTrigger>
                </Style.Triggers>
            </Style>