WPF实现ScrollViewer滚动到指定控件处
在前端UI开发中,有时,我们会遇到这样的需求:在一个ScrollViewer中有很多内容,而我们需要实现在执行某个操作后能够定位到其中指定的控件处;这很像在HTML页面中点击一个链接后定位到当前网页上的某个anchor。
要实现它,首先我们需要看ScrollViewer为我们提供的API,其中并没有类似于ScrollToControl这样的方法;在它的几个以ScrollTo开头的方法中,最合适的就是ScrollToVerticalOffset这个方法了,这个方法接受一个参数,即纵向的偏移位置。那么,很重要的问题:我们怎么能得到要定位的那个控件在ScrollViewer中的位置呢?
在我之前写的这篇文章中:XAML:获取元素的位置,有如何获到元素相对位置的介绍,建议大家先了解一下,其中使用了Visual.TransformToVisual方法等。当你理解了这篇文章后,再回过头来看本文后面的内容,就很容易了。
接下来,我们使用以下代码,即可实现上述需求:
//获取要定位之前ScrollViewer目前的滚动位置 varcurrentScrollPosition=ScrollViewer.VerticalOffset; varpoint=newPoint(0,currentScrollPosition); //计算出目标位置并滚动 vartargetPosition=TargetControl.TransformToVisual(ScrollViewer).Transform(point); ScrollViewer.ScrollToVerticalOffset(targetPosition.Y);
另外,由于通常情况下,我们会采用MVVM模式,因此我们可以将上述代码封装成一个Action,而避免在Code-Behind代码文件中添加上述代码。
新创建的名为ScrollToControlAction的Action,在其中定义两个依赖属性ScrollViewer和TargetControl,分别表示指定的要操作的ScrollViewer和要定位到的控件,然后将上述代码放到其Invoke方法中即可。由于Action并非本文主题,所以这里并不会展开太多的讲解,可以参考以下代码或本文后提供的Demo作进一步了解。
namespaceScrollTest { //////在ScrollViewer中定位到指定的控件 ///说明:目前支持的是垂直滚动 /// publicclassScrollToControlAction:TriggerAction{ publicstaticreadonlyDependencyPropertyScrollViewerProperty= DependencyProperty.Register("ScrollViewer",typeof(ScrollViewer),typeof(ScrollToControlAction),newPropertyMetadata(null)); publicstaticreadonlyDependencyPropertyTargetControlProperty= DependencyProperty.Register("TargetControl",typeof(FrameworkElement),typeof(ScrollToControlAction),newPropertyMetadata(null)); /// ///目标ScrollViewer /// publicScrollViewerScrollViewer { get{return(ScrollViewer)GetValue(ScrollViewerProperty);} set{SetValue(ScrollViewerProperty,value);} } //////要定位的到的控件 /// publicFrameworkElementTargetControl { get{return(FrameworkElement)GetValue(TargetControlProperty);} set{SetValue(TargetControlProperty,value);} } protectedoverridevoidInvoke(objectparameter) { if(TargetControl==null||ScrollViewer==null) { thrownewArgumentNullException($"{ScrollViewer}or{TargetControl}cannotbenull"); } //检查指定的控件是否在指定的ScrollViewer中 //TODO:这里只是指定离它最近的ScrollViewer,并没有继续向上找 varcontainer=TargetControl.FindParent(); if(container==null||container!=ScrollViewer) { thrownewException("TheTargetControlisnotinthetargetScrollViewer"); } //获取要定位之前ScrollViewer目前的滚动位置 varcurrentScrollPosition=ScrollViewer.VerticalOffset; varpoint=newPoint(0,currentScrollPosition); //计算出目标位置并滚动 vartargetPosition=TargetControl.TransformToVisual(ScrollViewer).Transform(point); ScrollViewer.ScrollToVerticalOffset(targetPosition.Y); } } }
其使用方法如下:
至此,结合Action,我们以非常灵活的方式实现了本文所提出的需求。
源码下载
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。