开发者

How to put image "placemarkers" inside a scrollbar in WPF?

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 开发者_JS百科this functionality in a few applications such as Eclipse and Chrome and was wondering how to reproduce it with WPF.


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.

How to put image "placemarkers" inside a scrollbar in WPF?


(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>


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜