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

 更新时间:2017年06月22日 13:46:43   作者:WPInfo   我要评论
这篇文章主要为大家详细介绍了WPF实现ScrollViewer滚动到指定控件处,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

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

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

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

// 获取要定位之前 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 作进一步了解。

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);
 }
 }
}

其使用方法如下:

<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,我们以非常灵活的方式实现了本文所提出的需求。

 源码下载

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持澳门金沙网上娱乐。

相关文章

  • .net decimal保留指定的小数位数(不四舍五入)

    .net decimal保留指定的小数位数(不四舍五入)

    大家都知道decimal保留指定位数小数的时候,.NET自带的方法都是四舍五入的。那么如何让decimal保留指定位数小数的时候不四舍五入呢,下面通过这篇文中的示例代码来一起看看吧。
    2016-12-12
  • C# 接口的隐式与显示实现及适应场景

    C# 接口的隐式与显示实现及适应场景

    以前在用到接口时,从来没注意到接口分为隐式实现与显示实现。昨天在浏览博客时看到相关内容,现在根据自己的理解记录一下,方便日后碰到的时候温习温习,需要的朋友可以了解下
    2012-12-12
  • ASP.NET MVC学习笔记

    ASP.NET MVC学习笔记

    ASP.NET MVC 1.0发布有段儿时间了,刚发布不久的时候试用了一下,做了一个简单的BBS,现在总结一些经验和小技巧和大家分享。
    2009-10-10
  • GridView控件实现数据的修改(第9节)

    GridView控件实现数据的修改(第9节)

    这篇文章主要介绍了GridView控件实现数据的修改,需要的朋友可以参考下
    2015-08-08
  • asp.net DataGrid 中文字符排序的实现代码

    asp.net DataGrid 中文字符排序的实现代码

    在论坛上看到有位朋友希望对中文按拼音进行排序,刚好最近有点空,贴一份原来一个同事写的一个排序类,仅稍微改动了下下,拿出来分享下.
    2009-09-09
  • WPF中在摄像头视频上叠加控件的解决方案

    WPF中在摄像头视频上叠加控件的解决方案

    前段时间,在一个wpf的项目中需要实时显示ip摄像头,对此的解决方案想必大家都应该知道很多。今天小编给大家带来了WPF中在摄像头视频上叠加控件的解决方案,一起看看吧
    2017-04-04
  • 深入Lumisoft.NET组件POP3邮件接收与删除操作的使用详解

    深入Lumisoft.NET组件POP3邮件接收与删除操作的使用详解

    本篇文章对Lumisoft.NET组件POP3邮件接收与删除操作的使用进行了详细的介绍。需要的朋友参考下
    2013-05-05
  • Repeater对数据进行格式化处理

    Repeater对数据进行格式化处理

    最近不止一个同学,问我在Repeater里怎么格式化数据,怎么处理。因为Repeater 属于服务器端控件。要么利用本身的控件事件来处理,要么在数据源上处理。
    2013-03-03
  • C#/.NET读取或修改文件的创建时间及修改时间详解

    C#/.NET读取或修改文件的创建时间及修改时间详解

    这篇文章主要给大家介绍了关于C#/.NET读取或修改文件的创建时间及修改时间的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • ASP.NET 2.0写无限级下拉菜单

    ASP.NET 2.0写无限级下拉菜单

    ASP.NET 2.0提供了一个Menu 类,可以方便地创建水平或者垂直方向的下拉菜单,下面就是一个例子:
    2008-12-12

最新评论