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,我们以非常灵活的方式实现了本文所提出的需求。
源码下载
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。