WPF: Implements ScrollViewer to scroll to the specified control, wpfscrollviewer
In front-end UI development, we sometimes encounter this requirement: there is a lot of content in a ScrollViewer, and we need to locate the specified control after performing an operation; this is similar to clicking a link on the HTML page to locate an anchor on the current page.
To implement it, first we need to look at the APIS provided by ScrollViewer for us. There is no method similar to ScrollToControl. In its several methods that start with ScrollTo, the most suitable method is ScrollToVerticalOffset. This method accepts a parameter, that is, the vertical offset position. So, how can we obtain the position of the control to be located in ScrollViewer?
In this article I wrote earlier: XAML: gets the position of an element and describes how to obtain the relative position of the element. We recommend that you understand it first, where Visual is used. transformToVisual method. After you understand this article, it is easy to go back and look at the content later in this article.
Next, we can use the following code to implement the above requirements:
// Obtain the current ScrollViewer rolling position var currentScrollPosition = ScrollViewer. verticalOffset; var point = new Point (0, currentScrollPosition); // calculate the target position and scroll var targetPosition = TargetControl. transformToVisual (ScrollViewer ). transform (point); ScrollViewer. scrollToVerticalOffset (targetPosition. Y );
In addition, we usually adopt the MVVM mode, so we can encapsulate the above Code into an Action, instead of adding the above Code to the Code-Behind Code file.
The newly created Action named ScrollToControlAction defines two dependency attributes: ScrollViewer and TargetControl, which respectively indicate the specified ScrollViewer to be operated and the control to be located, then place the above Code in its Invoke method. Because Action is not the topic of this article, it is not explained too much here. You can refer to the following code or the Demo provided later in this article for further understanding.
Namespace ScrollTest {/// <summary> /// locate the specified control in ScrollViewer /// description: currently, vertical scrolling is supported. // </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> /// target ScrollViewer /// </summary> public ScrollViewer {get {return (ScrollViewer) GetValue (ScrollViewerProperty);} set {SetValue (ScrollViewerProperty, value) ;}}/// <summary> /// control to be located /// </summary> public F RameworkElement 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 ");} // check whether the specified control is in the specified ScrollViewer. // TODO: Specify the ScrollV closest to the control. Iewer. var container = TargetControl. FindParent <ScrollViewer> (); if (container = null | container! = ScrollViewer) {throw new Exception ("The TargetControl is not in the target ScrollViewer");} // gets The current ScrollViewer rolling position var currentScrollPosition = ScrollViewer. verticalOffset; var point = new Point (0, currentScrollPosition); // calculate the target position and scroll var targetPosition = TargetControl. transformToVisual (ScrollViewer ). transform (point); ScrollViewer. scrollToVerticalOffset (targetPosition. Y );}}}
ScrollToControlAction. cs
The usage is as follows:
<Button> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <local:ScrollToControlAction ScrollViewer="{Binding ElementName=s}" TargetControl="{Binding ElementName=txtSectionC}" /> </i:EventTrigger> </i:Interaction.Triggers></Button>
At this point, combined with Action, we have implemented the requirements proposed in this article in a very flexible way.
Source code download