WPF Development Essays Collection-ScrollViewer Slider Too Small Solution

WPF Development Essays Collection-ScrollViewer Slider Too Small Solution

When the content in ScrollViewer is too long, the slider of the scroll bar becomes very small, which makes it less clickable.

最后更新 5/13/2022 7:13 AM
流浪g
预计阅读 4 分钟
分类
WPF
标签
.NET WPF

1. Preface

During the development of WPF, ScrollViewer was a commonly used control. In my work project, I received a feedback that when the content in ScrollViewer was too long, the slider of the scroll bar would become very small, which would make it less clickable. At first, I thought of setting the minimum value of the slider in the style, but it couldn't work. Finally, I changed the idea, by hiding the original slider and adding a control to serve as a slider to indirectly control the scrolling of ScrollViewer.

2. Main text

  1. Here, we will directly use the graph control written before to demonstrate it. When the graph has a lot of data, the slider will appear very small. Now, in the default style, it will be even smaller if it is in the custom style.

  1. Here, a Canvas is placed directly on the top level of the graph, and a Border is added to serve as a slider. Note that the entire Canvas is covered on the graph here because I also added the function of directly clicking on the graph and dragging it to move it. Then hide the slider of ScrollViewer, set the minimum width and height of the slider, and hide it by default
<Grid>
    <local:CruveDrawingVisual x:Name="curve" Margin="0,10,0,15" />
    <ScrollViewer
        Name="scroll"
        HorizontalScrollBarVisibility="Hidden"
        ScrollChanged="ScrollViewer_ScrollChanged"
        VerticalScrollBarVisibility="Disabled">
        <Canvas x:Name="canvas" />
    </ScrollViewer>
    <Canvas x:Name="CurvePanel" Background="Transparent">
        <Border
            x:Name="border"
            Canvas.Left="0"
            Canvas.Bottom="0"
            Height="15"
            MinWidth="80"
            Background="Green"
            PreviewMouseLeftButtonDown="Border_PreviewMouseLeftButtonDown"
            Visibility="Collapsed" />
    </Canvas>
</Grid>
  1. Then add the corresponding logical processing code in the background. Some detailed things have been written in the code in the form of remarks, so there is no need to talk about it here
public partial class MainWindow : Window
{
    private bool isAdd = true;
    private List<int> lists = new List<int>();

    private Point point_border;

    private double offset = -1;

    public MainWindow()
    {
        InitializeComponent();

        CurvePanel.MouseMove += delegate (object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                if (Mouse.Captured == null) Mouse.Capture(CurvePanel);

                //拖动滑块
                if (isBorder)
                {
                    Point point = e.GetPosition(this);
                    //鼠标超出控件左边缘
                    if (point.X - point_border.X <= 0)
                    {
                        scroll.ScrollToHorizontalOffset(0);
                    }
                    //鼠标超出控件右边缘
                    else if (point.X - point_border.X >= CurvePanel.ActualWidth - border.ActualWidth)
                    {
                        scroll.ScrollToHorizontalOffset(lists.Count - CurvePanel.ActualWidth);
                    }
                    //鼠标在控件区间
                    else if (point.X - point_border.X > 0 && point.X - point_border.X < CurvePanel.ActualWidth - border.ActualWidth)
                    {
                        double left = point.X - point_border.X;
                        scroll.ScrollToHorizontalOffset((lists.Count - CurvePanel.ActualWidth) / (CurvePanel.ActualWidth - border.ActualWidth) * left);
                    }
                }
                //拖动画布
                else
                {
                    if (offset >= 0 && offset <= CurvePanel.ActualWidth)
                    {
                        scroll.ScrollToHorizontalOffset(scroll.HorizontalOffset - (e.GetPosition(this).X - offset));
                    }
                    offset = e.GetPosition(this).X;
                }
            }
            else
            {
                offset = -1;
                isBorder = false;
                Mouse.Capture(null); // 释放鼠标捕获
            }
        };
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        int temp = 20;
        for (int i = 0; i < 24 * 60 * 60 * 2; i++)
        {
            if (isAdd)
            {
                lists.Add(temp);
                temp += 2;
            }
            else
            {
                lists.Add(temp);
                temp -= 2;
            }

            if (temp == 280) isAdd = false;
            if (temp == 20) isAdd = true;
        }
        canvas.Width = lists.Count;
        //判断是否显示滑块
        if (canvas.Width > CurvePanel.ActualWidth)
        {
            border.Visibility = Visibility.Visible;
            //根据ScrollViewer内容的比例计算滑块的宽度
            border.Width = CurvePanel.ActualWidth * CurvePanel.ActualWidth / canvas.Width;
        }
        else
        {
            border.Visibility = Visibility.Collapsed;
        }
        curve.SetupData(lists);
    }

    private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        curve.OffsetX(scroll.HorizontalOffset);

        Canvas.SetLeft(border, scroll.HorizontalOffset / ((lists.Count - CurvePanel.ActualWidth) / (CurvePanel.ActualWidth - border.ActualWidth)));
    }

    private bool isBorder = false;
    private void Border_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        isBorder = true;
        //获取鼠标点击滑块上的位置
        point_border = e.GetPosition(border);
    }
}
  1. The operating effect is as follows

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 9/13/2025

Migration from WPF to Avalonia series: Why I have to migrate WPF programs to Avalonia

In the past few years, our host computer software has been mainly developed using WPF and WinForm. These technologies are really easy to use on the Windows platform, and they have also accompanied us through the stage of small-scale trial production to today's large-scale delivery. However, with the development of business and changes in customer needs, the single Windows technology stack has gradually become a hurdle that we must overcome.

继续阅读
同分类 / 同标签 1/26/2025

WPF internationalizes with custom XML files

This article describes in detail the methods of using custom XML files to achieve internationalization in WPF programs, including installing the necessary NuGet package, dynamically obtaining language lists, dynamically switching languages, using translation strings in code and xaml interfaces, etc. It also provides source code links to help developers easily internationalize WPF applications.

继续阅读