How to put image “placemarkers” inside a scrollbar in WPF?

后端 未结 2 1317
栀梦
栀梦 2021-02-14 03:27

I have a long Scroll Viewer and I want to mark important spots with small images on the scroll bar. If the the image is clicked the scroll bar will jump to the corresponding con

相关标签:
2条回答
  • 2021-02-14 04:00

    Short answer is "change the template of the ScrollBar".

    Long answer is... That I would add an ItemsControl in the template of the ScrollBar control. I would put this ItemsControl on top of the template with its IsHitTestVisible set to false so that it does not capture mouse events.

    Then I would use a Canvas as the ItemsPanelTemplate in order to be able to place the spots properly. I would use databinding with the ItemsSource property of the ItemsControl and a DataTemplate in order to render each element with an image.

    Here is a sample that I did using Blend. Of course it's not complete (it does not handle mouse event for example), but I hope it will be a starting point for you.


    (source: japf.fr)

    <ControlTemplate TargetType="{x:Type ScrollBar}">
        <Grid SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
                <ColumnDefinition Width="0.00001*"/>
                <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
            </Grid.ColumnDefinitions>
            <RepeatButton Style="{StaticResource ScrollBarButton}" Command="{x:Static ScrollBar.LineLeftCommand}" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="LeftArrow"/>
            <Track x:Name="PART_Track" Grid.Column="1" d:IsHidden="True">
                <Track.Thumb>
                    <Thumb Style="{StaticResource ScrollBarThumb}" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="HorizontalGripper"/>
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <RepeatButton Style="{StaticResource HorizontalScrollBarPageButton}" Command="{x:Static ScrollBar.PageRightCommand}"/>
                </Track.IncreaseRepeatButton>
                <Track.DecreaseRepeatButton>
                    <RepeatButton Style="{StaticResource HorizontalScrollBarPageButton}" Command="{x:Static ScrollBar.PageLeftCommand}"/>
                </Track.DecreaseRepeatButton>
            </Track>
            <ItemsControl Grid.Column="1" HorizontalAlignment="Stretch">
                <sys:Double>10</sys:Double>
                <sys:Double>50</sys:Double>
                <sys:Double>100</sys:Double>
                <sys:Double>140</sys:Double>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Rectangle Fill="Orange" Width="3" Height="16"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Left" Value="{Binding }" />
                    </Style>
                                            </ItemsControl.ItemContainerStyle>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
            <RepeatButton Style="{StaticResource ScrollBarButton}" Grid.Column="2" Command="{x:Static ScrollBar.LineRightCommand}" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="RightArrow" d:IsHidden="True"/>
        </Grid>
    </ControlTemplate>
    
    0 讨论(0)
  • 2021-02-14 04:08

    To contribute to japfs answer: I solved the update on resize issue: You can use japfs Style and apply a ItemsSource to the ItemControl:

    ItemsSource="{Binding Positions, UpdateSourceTrigger=PropertyChanged}"
    

    Just make sure Positions is of type ObservableCollection and the positions are recalculated in SizeChanged-event. Additionally in that event call (INotifyPropertyChanged interface which should your ViewModel implement)

    OnPropertyChanged("Positions");
    

    Tried it with a List first, but that did not update correctly. Worked with ObservableCollection just fine.

    0 讨论(0)
提交回复
热议问题