none
How to fix ListView headers and let only content scroll RRS feed

  • Question

  • I am using WPF ListView with scroll and I don't want the headers to scroll with the ListView items.

    Any suggestions ?

    Thanks,
    Tuesday, March 18, 2008 12:02 PM

Answers

  • Here is an XAMLPad ready example of changing the ListView's control template to achieve this type of scenario:

    Code Snippet

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Page.Resources>
            <SolidColorBrush x:Key="ListBorder" Color="#FF7F9DB9"/>
            <Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}" TargetType="{x:Type ScrollViewer}">
                <Setter Property="Focusable" Value="false"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ScrollViewer}">
                            <Grid SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <DockPanel Margin="{TemplateBinding Padding}">
                                    <ScrollContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ScrollContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" KeyboardNavigation.DirectionalNavigation="Local" CanContentScroll="{TemplateBinding CanContentScroll}"/>
                                </DockPanel>
                                <ScrollBar Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_HorizontalScrollBar" Grid.Row="1" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0.0" Value="{Binding Path=HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                                <ScrollBar Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_VerticalScrollBar" Grid.Column="1" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0.0" Value="{Binding Path=VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                                <DockPanel Grid.Column="1" Grid.Row="1" Background="{Binding Path=Background, ElementName=PART_VerticalScrollBar}" LastChildFill="false">
                                    <Rectangle Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Fill="White" Width="1" DockPanel.Dock="Left"/>
                                    <Rectangle Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Fill="White" Height="1" DockPanel.Dock="Top"/>
                                </DockPanel>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style TargetType="{x:Type ListView}">
                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
                <Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListView}">
                            <Border
                                SnapsToDevicePixels="true"
                                x:Name="Bd"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                                <DockPanel>
                                    <GridViewHeaderRowPresenter
                                        DockPanel.Dock="Top"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                        Columns="{Binding Path=View.Columns, RelativeSource={RelativeSource TemplatedParent}}"
                                        AllowsColumnReorder="{Binding Path= View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderContainerStyle="{Binding Path=View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderContextMenu="{Binding Path=View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderTemplate="{Binding Path=View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderTemplateSelector="{Binding Path=View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderToolTip="{Binding Path=View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}"/>
                                    
                                    <ScrollViewer Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}" Padding="{TemplateBinding Padding}">
                                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                    </ScrollViewer>
                                </DockPanel>
                            
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsGrouping" Value="true">
                                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Page.Resources>
        <Grid>
            <ListView Width="400" Height="60">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
                        <GridViewColumn Header="Namespace" DisplayMemberBinding="{Binding Namespace}"/>
                    </GridView>
                </ListView.View>
                <x:Type TypeName="Visual"/>
                <x:Type TypeName="UIElement"/>
                <x:Type TypeName="FrameworkElement"/>
            </ListView>
        </Grid>
    </Page>



    Hope this helps
    Thursday, March 20, 2008 4:49 AM

All replies

  • Here is an XAMLPad ready example of changing the ListView's control template to achieve this type of scenario:

    Code Snippet

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Page.Resources>
            <SolidColorBrush x:Key="ListBorder" Color="#FF7F9DB9"/>
            <Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}" TargetType="{x:Type ScrollViewer}">
                <Setter Property="Focusable" Value="false"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ScrollViewer}">
                            <Grid SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <DockPanel Margin="{TemplateBinding Padding}">
                                    <ScrollContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ScrollContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" KeyboardNavigation.DirectionalNavigation="Local" CanContentScroll="{TemplateBinding CanContentScroll}"/>
                                </DockPanel>
                                <ScrollBar Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_HorizontalScrollBar" Grid.Row="1" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0.0" Value="{Binding Path=HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                                <ScrollBar Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_VerticalScrollBar" Grid.Column="1" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0.0" Value="{Binding Path=VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                                <DockPanel Grid.Column="1" Grid.Row="1" Background="{Binding Path=Background, ElementName=PART_VerticalScrollBar}" LastChildFill="false">
                                    <Rectangle Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Fill="White" Width="1" DockPanel.Dock="Left"/>
                                    <Rectangle Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Fill="White" Height="1" DockPanel.Dock="Top"/>
                                </DockPanel>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style TargetType="{x:Type ListView}">
                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
                <Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListView}">
                            <Border
                                SnapsToDevicePixels="true"
                                x:Name="Bd"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                                <DockPanel>
                                    <GridViewHeaderRowPresenter
                                        DockPanel.Dock="Top"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                        Columns="{Binding Path=View.Columns, RelativeSource={RelativeSource TemplatedParent}}"
                                        AllowsColumnReorder="{Binding Path= View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderContainerStyle="{Binding Path=View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderContextMenu="{Binding Path=View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderTemplate="{Binding Path=View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderTemplateSelector="{Binding Path=View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}"
                                        ColumnHeaderToolTip="{Binding Path=View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}"/>
                                    
                                    <ScrollViewer Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}" Padding="{TemplateBinding Padding}">
                                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                    </ScrollViewer>
                                </DockPanel>
                            
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsGrouping" Value="true">
                                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Page.Resources>
        <Grid>
            <ListView Width="400" Height="60">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
                        <GridViewColumn Header="Namespace" DisplayMemberBinding="{Binding Namespace}"/>
                    </GridView>
                </ListView.View>
                <x:Type TypeName="Visual"/>
                <x:Type TypeName="UIElement"/>
                <x:Type TypeName="FrameworkElement"/>
            </ListView>
        </Grid>
    </Page>



    Hope this helps
    Thursday, March 20, 2008 4:49 AM
  • Thanks a lot Marco,

     Got it working using your example.

     
    Friday, March 21, 2008 4:11 AM