Как поместить изображения «меток» в полосу прокрутки в WPF? - PullRequest
11 голосов
/ 22 января 2010

У меня длинный Scroll Viewer, и я хочу пометить важные места маленькими изображениями на полосе прокрутки. Если щелкнуть изображение, полоса прокрутки перейдет к соответствующему содержимому.

Я видел эту функцию в нескольких приложениях, таких как Eclipse и Chrome , и задавался вопросом, как воспроизвести ее с WPF.

Ответы [ 2 ]

12 голосов
/ 22 января 2010

Краткий ответ: «Измените шаблон ScrollBar».

Длинный ответ ... Я бы добавил ItemsControl в шаблон элемента управления ScrollBar. Я бы поместил этот ItemsControl поверх шаблона с IsHitTestVisible, установленным в false, чтобы он не захватывал события мыши.

Тогда я бы использовал Canvas в качестве ItemsPanelTemplate, чтобы иметь возможность правильно размещать пятна. Я бы использовал привязку данных со свойством ItemsSource ItemsControl и DataTemplate, чтобы визуализировать каждый элемент с изображением.

Вот пример, который я сделал, используя Blend. Конечно, он не завершен (например, он не обрабатывает события мыши), но я надеюсь, что он станет отправной точкой для вас.

alt text
(источник: 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>
1 голос
/ 21 апреля 2017

Чтобы внести свой вклад в ответ japfs: Я решил обновление по проблеме изменения размера: Вы можете использовать стиль japfs и применить ItemSource к ItemControl:

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

Просто убедитесь, что Positions имеет тип ObservableCollection и позиции пересчитываются в SizeChanged-событие. Кроме того, в этом вызове события (интерфейс INotifyPropertyChanged, который должен реализовать ваш ViewModel)

OnPropertyChanged("Positions");

Сначала попробовал со списком, но он не обновился правильно. Работал с ObservableCollection просто отлично.

...