0
votes

I have created a custom template for the scrollbar (horizontal) which contains now just the two scroll buttons without the scrollbar, both of which are in a separate grid column. I want the right button to disappear when we can no longer scroll to the right and vice versa for the left button. I can set the scrollbar visibility in the scrollviewer template to:

Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"

Which will only show the scrollbar when necessary but don’t see any property within the scrollbar that would expose when the scrollbar has reached its rightmost or leftmost position that I could bind the visibility property to… Not sure really how to go about this one so any advice would be great.

2

2 Answers

1
votes

It can be done like this...

<MenuScrollingVisibilityConverter x:Key="MenuScrollingVisibilityConverter" />

<Style x:Key="HorizontalScrollViewerStyle"
      TargetType="{x:Type ScrollViewer}">
  <Setter Property="OverridesDefaultStyle"
          Value="True" />
  <Setter Property="Template">
     <Setter.Value>
        <ControlTemplate TargetType="{x:Type ScrollViewer}">
           <Grid>
              <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="Auto" />
                 <ColumnDefinition />
                 <ColumnDefinition Width="Auto" />
              </Grid.ColumnDefinitions>
              <ScrollContentPresenter Grid.Column="1" />
              <RepeatButton Command="{x:Static ScrollBar.LineLeftCommand}"
                            CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=.}">
                 <RepeatButton.Visibility>
                    <MultiBinding Converter="{StaticResource MenuScrollingVisibilityConverter}"
                                  ConverterParameter="0"
                                  FallbackValue="Visibility.Collapsed">
                       <Binding Path="ComputedHorizontalScrollBarVisibility"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                       <Binding Path="HorizontalOffset"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                       <Binding Path="ExtentWidth"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                       <Binding Path="ViewportWidth"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                    </MultiBinding>
                 </RepeatButton.Visibility>
              </RepeatButton>
              <RepeatButton Grid.Column="2"
                            Command="{x:Static ScrollBar.LineRightCommand}"
                            CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=.}">
                 <RepeatButton.Visibility>
                    <MultiBinding Converter="{StaticResource MenuScrollingVisibilityConverter}"
                                  ConverterParameter="100"
                                  FallbackValue="Visibility.Collapsed">
                       <Binding Path="ComputedHorizontalScrollBarVisibility"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                       <Binding Path="HorizontalOffset"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                       <Binding Path="ExtentWidth"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                       <Binding Path="ViewportWidth"
                                RelativeSource="{RelativeSource TemplatedParent}" />
                    </MultiBinding>
                 </RepeatButton.Visibility>
              </RepeatButton>
           </Grid>
        </ControlTemplate>
     </Setter.Value>
  </Setter>
</Style>
0
votes

Scrolling in WPF is taken care of by the IScrollInfo Interface. Its LineLeft(), LineRight(), PageLeft() and PageRight() methods do the actual content scrolling and are executed by the various RepeatButtons in the ScrollBar ControlTemplate. It also provides the HorizontalOffset, ViewportWidth and ExtentWidth properties that you can use to determine where the scrolled content is. These methods and properties are exposed on the ScrollViewer class.

While I haven't tried this, I believe that you can detect when the content is scrolled to the far right like this:

bool isAtRightSide = HorizontalOffset >= ExtentWidth - ViewportWidth;

The HorizontalOffset property gets the horizontal offset of the scrolled content.
The ExtentWidth property gets the horizontal size of the extent. (Total size)
The ViewportWidth property gets the horizontal size of the viewport for this content.