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

和自甴很熟 提交于 2019-12-05 15:27:47

问题


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 content.

I've seen this functionality in a few applications such as Eclipse and Chrome and was wondering how to reproduce it with WPF.


回答1:


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>



回答2:


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.



来源:https://stackoverflow.com/questions/2114965/how-to-put-image-placemarkers-inside-a-scrollbar-in-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!