Click here to Skip to main content
15,885,782 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I want to remove or replace the ScrollViewer found in the template of a wpf DataGrid. The reason i want to do this is because the datagrid won't support smooth scrolling as a result of me using a custom scrollbar in my app. But i have faced this similar problem of loosing smooth scrolling capability when i used a treeview but i solved it be removing the scrollviewer from the TreeView's template. Below is the default template for a WPF TreeView.

<Style x:Key="{x:Type TreeView}"
           TargetType="{x:Type TreeView}">
        <Setter Property="Background"
                Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
        <Setter Property="BorderBrush"
                Value="{StaticResource ListBorder}"/>
        <Setter Property="BorderThickness"
                Value="1"/>
        <Setter Property="Padding"
                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.PanningMode"
                Value="Both"/>
        <Setter Property="Stylus.IsFlicksEnabled"
                Value="False"/>
        <Setter Property="VerticalContentAlignment"
                Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TreeView}">
                    <Border Name="Bd"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            SnapsToDevicePixels="true">
                        <ScrollViewer Name="_tv_scrollviewer_"
                                      Background="{TemplateBinding Background}"
                                      Focusable="false"
                                      CanContentScroll="false"
                                      HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                                      VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                                      Padding="{TemplateBinding Padding}"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
                            <ItemsPresenter/>
                        </ScrollViewer>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled"
                                 Value="false">
                            <Setter TargetName="Bd"
                                    Property="Background"
                                    Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        </Trigger>
                      <Trigger Property="VirtualizingPanel.IsVirtualizing"
                               Value="true">
                        <Setter TargetName="_tv_scrollviewer_"
                                Property="CanContentScroll"
                                Value="true"/>
                      </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
      <Style.Triggers>
        <Trigger Property="VirtualizingPanel.IsVirtualizing"
                 Value="true">
          <Setter Property="ItemsPanel">
            <Setter.Value>
              <ItemsPanelTemplate>
                <VirtualizingStackPanel/>
              </ItemsPanelTemplate>
            </Setter.Value>
          </Setter>
        </Trigger>
      </Style.Triggers>
    </Style>


Below is the template i redefined, that is, the template in which the scrollviewer is removed so i can have smooth scrolling when the mouse is over the TreeView control.


<Style x:Key="RoleTreeViewStyle" TargetType="{x:Type TreeView}" BasedOn="{StaticResource BaseStyle}">
      <Setter Property="Background" Value="{StaticResource BackgroundVeryLightBrush}"/>
      <Setter Property="Foreground" Value="{StaticResource ForegroundVeryDarkBrush}"/>
      <Setter Property="BorderThickness" Value="0"/>
      <Setter Property="Padding" Value="0 5"/>
      <Setter Property="VerticalContentAlignment" Value="Center"/>
      <Setter Property="FontFamily" Value="{StaticResource LatoRegular}" />
      <Setter Property="FontSize" Value="{StaticResource FontSizeLarge}" />
      <Setter Property="VerticalAlignment" Value="Top" />
      <Setter Property="HorizontalAlignment" Value="Left" />
      <Setter Property="Margin" Value="5 0 5 0" />
      <Setter Property="Template">
          <Setter.Value>
              <ControlTemplate TargetType="{x:Type TreeView}">
                  <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}"
                      BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                      <StackPanel>
                          <ItemsPresenter/>
                      </StackPanel>
                  </Border>

                  <ControlTemplate.Triggers>
                      <Trigger Property="IsEnabled" Value="false">
                          <Setter Property="Panel.Background" TargetName="Bd"
                          Value="{StaticResource WordVeryVeryLightBlueBrush}"/>
                      </Trigger>
                  </ControlTemplate.Triggers>

              </ControlTemplate>
          </Setter.Value>
      </Setter>
      <Style.Triggers>
          <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
              <Setter Property="ItemsPanel">
                  <Setter.Value>
                      <ItemsPanelTemplate>
                          <VirtualizingStackPanel/>
                      </ItemsPanelTemplate>
                  </Setter.Value>
              </Setter>
          </Trigger>
      </Style.Triggers>
  </Style>



So in the second template, i replaced the ScrollViewer with a StackPanel.
So my question is how can i do something similar with the DataGrid template below without affecting the DataGrid display and functionality? My main goal is to remove/replace the ScrollViewer in the template without affecting the DataGrid's funtionality.

DataGrid default template

<Style x:Key="{x:Type DataGrid}" 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}"
                      SnapsToDevicePixels="True"
                      Padding="{TemplateBinding Padding}">
                        <ScrollViewer   Focusable="false"
                                Name="DG_ScrollViewer">
                            <ScrollViewer.Template>
                                <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="*"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>

                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="Auto"/>
                                        </Grid.ColumnDefinitions>

                                        <Button Command="{x:Static DataGrid.SelectAllCommand}"
                                                Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=CellsPanelHorizontalOffset}"
                                                Style="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type DataGrid}, ResourceId=DataGridSelectAllButtonStyle}}"
                                                Focusable="false"
                                                Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.All}}" />
                                        <DataGridColumnHeadersPresenter Grid.Column="1"
                                                           Name="PART_ColumnHeadersPresenter"
                                                           Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>

                                        <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />

                                        <ScrollBar Grid.Row="1" 
                                                 Grid.Column="2" 
                                                 Name="PART_VerticalScrollBar"
                                                 Orientation="Vertical"
                                                 Maximum="{TemplateBinding ScrollableHeight}"
                                                 ViewportSize="{TemplateBinding ViewportHeight}"
                                                 Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                                 Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>

                                        <Grid Grid.Row="2" Grid.Column="1">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/>
                                                <ColumnDefinition Width="*"/>
                                            </Grid.ColumnDefinitions>
                                            <ScrollBar Grid.Column="1"
                                                       Name="PART_HorizontalScrollBar"
                                                       Orientation="Horizontal"
                                                       Maximum="{TemplateBinding ScrollableWidth}"
                                                       ViewportSize="{TemplateBinding ViewportWidth}"
                                                       Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                                       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> 

Any help or hint will be greatly appreciated.

What I have tried:

I have tried to replaced it with a StackPanel, ContentPresenter etc but none of these controls support Templates as i get error message such as "The type Template is not recognized or accessible" when i do <stackpanel.template>.
Posted
Updated 18-Feb-19 6:53am
v3

1 solution

><pre><pre lang="c#"></pre></pre><code><code><code><code><code><code><code><code>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900