一、前言
在WPF開發過程中,ScrollViewer是一個很常使用到的控件,在自己工作的項目中,收到一個反饋就是當ScrollViewer里面的內容太長時,滾動條的滑塊就會變得很小,然后導致點擊起來不太友好。一開始想着是通過在樣式里面設置滑塊的最小值,但都沒法生效。最后換了一個思路來,通過把原有的滑塊隱藏,然后自己加一個控件來充當滑塊來間接控制ScrollViewer的滾動。
二、正文
1、這里就直接拿之前寫的那個曲線圖控件來進行演示,當曲線圖的數據很多時,滑塊就會顯得很小個,現在實在默認樣式情況下,如果在自定義的樣式情況下很更小
2、這里就直接在曲線圖的頂層放置了一個Canvas,添加一個Border來充當滑塊,注意這里將整個Canvas覆蓋再曲線圖上,是因為我還添加了可以直接點擊曲線圖拖拽移動的功能,然后將ScrollViewer的滑塊隱藏,設置好滑塊的最小寬度和高度,默認隱藏
<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>
3、接着再后台添加對應的邏輯處理代碼,詳細的一些東西都已經通過備注的形式寫在代碼里,這里就不在啰嗦了
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); } }
4、運行效果如下