WPF实现ScrollViewer滚动到指定控件处

2025-05-29 0 89

在前端 UI 开发中,有时,我们会遇到这样的需求:在一个 ScrollViewer 中有很多内容,而我们需要实现在执行某个操作后能够定位到其中指定的控件处;这很像在 HTML 页面中点击一个链接后定位到当前网页上的某个 anchor。

要实现它,首先我们需要看 ScrollViewer 为我们提供的 API,其中并没有类似于 ScrollToControl 这样的方法;在它的几个以 ScrollTo 开头的方法中,最合适的就是 ScrollToVerticalOffset 这个方法了,这个方法接受一个参数,即纵向的偏移位置。那么,很重要的问题:我们怎么能得到要定位的那个控件在 ScrollViewer 中的位置呢?

在我之前写的这篇文章中:XAML: 获取元素的位置,有如何获到元素相对位置的介绍,建议大家先了解一下,其中使用了 Visual.TransformToVisual 方法等。当你理解了这篇文章后,再回过头来看本文后面的内容,就很容易了。

接下来,我们使用以下代码,即可实现上述需求:

?

1

2

3

4

5

6

7
// 获取要定位之前 ScrollViewer 目前的滚动位置

var currentScrollPosition = ScrollViewer.VerticalOffset;

var point = new Point(0, currentScrollPosition);

// 计算出目标位置并滚动

var targetPosition = TargetControl.TransformToVisual(ScrollViewer).Transform(point);

ScrollViewer.ScrollToVerticalOffset(targetPosition.Y);

另外,由于通常情况下,我们会采用 MVVM 模式,因此我们可以将上述代码封装成一个 Action,而避免在 Code-Behind 代码文件中添加上述代码。

新创建的名为 ScrollToControlAction 的 Action,在其中定义两个依赖属性 ScrollViewer 和 TargetControl,分别表示指定的要操作的 ScrollViewer 和要定位到的控件,然后将上述代码放到其 Invoke 方法中即可。由于 Action 并非本文主题,所以这里并不会展开太多的讲解,可以参考以下代码或本文后提供的 Demo 作进一步了解。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57
namespace ScrollTest

{

/// <summary>

/// 在 ScrollViewer 中定位到指定的控件

/// 说明:目前支持的是垂直滚动

/// </summary>

public class ScrollToControlAction : TriggerAction<FrameworkElement>

{

public static readonly DependencyProperty ScrollViewerProperty =

DependencyProperty.Register("ScrollViewer", typeof(ScrollViewer), typeof(ScrollToControlAction), new PropertyMetadata(null));

public static readonly DependencyProperty TargetControlProperty =

DependencyProperty.Register("TargetControl", typeof(FrameworkElement), typeof(ScrollToControlAction), new PropertyMetadata(null));

/// <summary>

/// 目标 ScrollViewer

/// </summary>

public ScrollViewer ScrollViewer

{

get { return (ScrollViewer)GetValue(ScrollViewerProperty); }

set { SetValue(ScrollViewerProperty, value); }

}

/// <summary>

/// 要定位的到的控件

/// </summary>

public FrameworkElement TargetControl

{

get { return (FrameworkElement)GetValue(TargetControlProperty); }

set { SetValue(TargetControlProperty, value); }

}

protected override void Invoke(object parameter)

{

if (TargetControl == null || ScrollViewer == null)

{

throw new ArgumentNullException($"{ScrollViewer} or {TargetControl} cannot be null");

}

// 检查指定的控件是否在指定的 ScrollViewer 中

// TODO: 这里只是指定离它最近的 ScrollViewer,并没有继续向上找

var container = TargetControl.FindParent<ScrollViewer>();

if (container == null || container != ScrollViewer)

{

throw new Exception("The TargetControl is not in the target ScrollViewer");

}

// 获取要定位之前 ScrollViewer 目前的滚动位置

var currentScrollPosition = ScrollViewer.VerticalOffset;

var point = new Point(0, currentScrollPosition);

// 计算出目标位置并滚动

var targetPosition = TargetControl.TransformToVisual(ScrollViewer).Transform(point);

ScrollViewer.ScrollToVerticalOffset(targetPosition.Y);

}

}

}

其使用方法如下:

?

1

2

3

4

5

6

7
<Button>

<i:Interaction.Triggers>

<i:EventTrigger EventName="Click">

<local:ScrollToControlAction ScrollViewer="{Binding ElementName=s}" TargetControl="{Binding ElementName=txtSectionC}" />

</i:EventTrigger>

</i:Interaction.Triggers>

</Button>

至此,结合 Action,我们以非常灵活的方式实现了本文所提出的需求。

源码下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

原文链接:http://www.cnblogs.com/wpinfo/archive/2017/06/22/7063584.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 WPF实现ScrollViewer滚动到指定控件处 https://www.kuaiidc.com/99762.html

相关文章

发表评论
暂无评论