具有不同行颜色的ListBox滚动条

4

我希望自定义我的ListBox 垂直滚动条,以蓝色标记显示当前选定项目位置,就像在VS编辑器中一样,并且还想在垂直滚动条线上显示listboxitem的背景颜色

enter image description here

我怎么能实现这个?


你需要重新设计ScrollBar的模板,并添加绘制颜色的代码。 我无法给你完整的代码示例,因为完成代码可能需要数小时甚至更长时间。 - Ketobomb
可以,但您可以给我一个小样本吗?我如何获取滚动条上的精确位置以绘制颜色? - Amol Bavannavar
2个回答

3
这是您定制的滚动查看器:

public class MyScrollViewer : ScrollViewer
{
    static MyScrollViewer()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyScrollViewer), new FrameworkPropertyMetadata(typeof(MyScrollViewer)));
    }


}

通过其XAML:
<Style TargetType="{x:Type local:MyScrollViewer}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyScrollViewer}">
                <Grid>
                    <ScrollContentPresenter />
                    <local:MyScrollBar Name="PART_HorizontalScrollBar" Orientation="Horizontal" Value="{TemplateBinding HorizontalOffset}"
                             Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}" 
                             Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这里是ScrollViewer使用的自定义滚动条:
public class MyScrollBar : ScrollBar
{
    static MyScrollBar()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyScrollBar), new FrameworkPropertyMetadata(typeof(MyScrollBar)));
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        var canvas = Template.FindName("PART_Canvas", this) as Canvas;

        if (canvas != null)
        {
            //draw something onto the canvas
            Line myLine = new Line();

            myLine.Stroke = System.Windows.Media.Brushes.Red;

            myLine.X1 = 100;
            myLine.X2 = 140;  
            myLine.Y1 = 200;
            myLine.Y2 = 200;

            myLine.StrokeThickness = 1;

            canvas.Children.Add(myLine);
        }
    }
}

还有使用XAML的方式:

<Style TargetType="{x:Type local:MyScrollBar}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyScrollBar}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MaxWidth="18"/>
                            <ColumnDefinition Width="0.00001*"/>
                            <ColumnDefinition MaxWidth="18"/>
                        </Grid.ColumnDefinitions>
                        <Border Grid.ColumnSpan="3" CornerRadius="2" Background="Transparent" />
                        <RepeatButton  Grid.Column="0" Width="18" Command="ScrollBar.LineLeftCommand" Content="M 4 0 L 4 8 L 0 4 Z" />
                        <Canvas x:Name="PART_Canvas" Grid.Column="1" />
                        <RepeatButton Grid.Column="2"  Width="18" Command="ScrollBar.LineRightCommand" Content="M 0 0 L 4 4 L 0 8 Z"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这里是Windows系统使用此控件的示例:

<Window x:Class="VSScroller.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:VSScroller"
    Title="MainWindow" Height="350" Width="525">

<Grid>
    <local:MyScrollViewer HorizontalScrollBarVisibility="Visible" Background="Yellow">
        <TextBlock>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's <LineBreak/>
                   standard dummy text ever since the 1500s, when an unknown printer <LineBreak/>
            took a galley of type and scrambled it to make a <LineBreak/>
                   type specimen book. It has survived not only five centuries, <LineBreak/>
            but also the leap into electronic typesetting, remaining 
                   essentially unchanged. It was popularised in the 1960s with <LineBreak/>
            the release of Letraset sheets containing Lorem Ipsum passages, <LineBreak/>
                   and more recently with desktop publishing software like Aldus <LineBreak/>
            PageMaker including versions of Lorem Ipsum.</TextBlock>
    </local:MyScrollViewer>
</Grid>


现在,您可以添加自定义逻辑以将颜色绘制到ScrollBar画布上。 - Ketobomb
谢谢您的回答,但我的问题仍然是如何找到滚动条上确切的位置以绘制背景颜色? - Amol Bavannavar
不确定我是否真正理解这个问题。您是在询问放置蓝色标记的算法吗? - Ketobomb
不是算法的问题,而是如何获取滚动条上的位置以将 ListBoxItem 的背景颜色绘制到滚动条上? - Amol Bavannavar
2
我不了解你的代码。但是你需要在画布上绘制标记(颜色)。获取画布的高度(或宽度)(.ActualHeight)。假设你的 ListBox 有10个项,而第5个是你想要在滚动条上标记的项,则可以在画布的中心处进行标记。 - Ketobomb
1
非常感谢你,这个完全没有问题。得到了我想要的结果。 - Amol Bavannavar

0

是的,Naadof。但我需要一个简要的想法,关于如何实现这个功能?我该如何在垂直滚动条上获取ListBoxItem的精确位置,并用相应的ListBoxItem背景刷绘制该区域? - Amol Bavannavar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接