当前位置: 移动技术网 > IT编程>开发语言>.net > WPF实现ScrollViewer滚动到指定控件处

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

2017年12月08日  | 移动技术网IT编程  | 我要评论

天子传奇8,viewstate用法,异世之恶魔猎手

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网