如何在图像上添加“地标” WPF 中的滚动条内?

发布于 2024-08-18 22:55:42 字数 234 浏览 1 评论 0原文

我有一个长滚动查看器,我想在滚动条上用小图像标记重要点。如果单击图像,滚动条将跳转到相应的内容。

我已经在一些应用程序中看到了此功能,例如 Eclipse 和 Chrome 并想知道如何使用 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 this functionality in a few applications such as Eclipse and Chrome and was wondering how to reproduce it with WPF.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情何以堪。 2024-08-25 22:55:42

简短的回答是“更改 ScrollBar 的模板”。

长答案是...我将在 ScrollBar 控件的模板中添加一个 ItemsControl 。我会将此 ItemsControl 放在模板顶部,并将其 IsHitTestVisible 设置为 false,以便它不会捕获鼠标事件。

然后我将使用 Canvas 作为 ItemsPanelTemplate 以便能够正确放置这些点。我将使用数据绑定与 ItemsControl 的 ItemsSource 属性和 DataTemplate 以便使用图像呈现每个元素。

这是我使用 Blend 制作的示例。当然它并不完整(例如它不处理鼠标事件),但我希望它将成为您的起点。

替代文本
(来源: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>

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.

alt text
(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>
行雁书 2024-08-25 22:55:42

为 japfs 答案做出贡献:
我解决了调整大小问题的更新:
您可以使用 japfs Style 并将 ItemsSource 应用于 ItemControl:

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

只需确保 Positions 为 ObservableCollection 类型,并且在 SizeChanged 事件中重新计算位置。另外,在该事件调用中(您的 ViewModel 应该实现的 INotifyPropertyChanged 接口)

OnPropertyChanged("Positions");

首先尝试使用列表,但没有正确更新。与 ObservableCollection 一起工作得很好。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文