This article is the analysis of the. NET Framework source code series, mainly tells you Microsoft to do ScrollViewer's train of thought, the analysis is very simple.
After reading this article, you can learn how to write a ScrollViewer, how to define a iscrollinfo, or to scroll to add animation using
The following tells you how to use ScrollViewer, generally in the need to scroll the control outside a ScrollViewer can be implemented scrolling.
<scrollviewer horizontalscrollbarvisibility= "Auto" >
<stackpanel verticalalignment= "Top" Horizontalalignment= "Left" >
<textblock textwrapping= "Wrap" margin= "0,0,0,20" >scrolling are enabled when It is necessary.
Resize the window, making it larger and smaller.</textblock>
<rectangle fill= "Red" width= "500" ></Rectangle>
</StackPanel>
</ScrollViewer>
But not all of the controls put a scrollviewer outside can scroll because scrolling actually requires the control to do it itself. principle
Let's show you how scrolling is done.
One of the easiest ways to set the transform.y of an element is to scroll through this way is the easiest way, but the disadvantage is that other controls cannot move other things.
There are two scrolling modes in ScrollViewer, physical scrolling and logical scrolling, if you use physical scrolling so that scrolling is scrollviewer and how to use logical scrolling, then scrolling is what the controls do.
So I start with the input from the ScrollViewer receive input
If you use ScrollViewer for scrolling, you may encounter a magical need to scroll through the touch. Yes, if using a simple scrollviewer is not able to use touch scrolling
Look at the code, write a simple scrollviewer there are some rectangles, you can see the mouse scrolling, but the touch is unable to scroll.
<Grid>
<ScrollViewer>
<stackpanel x:name= "Hcrkkmqnnfzo" ></StackPanel>
</ Scrollviewer>
</Grid>
Traverse the color in the background and add
Public MainWindow ()
{
InitializeComponent ();
foreach (var temp in typeof (brushes)
. GetProperties (bindingflags.static | BindingFlags.Public | BindingFlags.NonPublic)
. Select (Temp => temp. GetValue (null, NULL))
{
var rectangle = new Rectangle
{
Height =,
Fill = (Brush) temp
};< C12/>hcrkkmqnnfzo.children.add (rectangle);
}
Code: WPF ScrollView Code interpretation 1.1-csdn Download
If there is no csdn integral, try to use My network disk, but if my network is expired please let me know.
If you need to use scrolling in touch, then you need to set Panningmode and you can set up support for vertical drag.
If you set the Panningmode, you will find the drag to let the window jitter, you need to rewrite the onmanipulationboundaryfeedback in the window, see the following code. Function inside do not write anything, please see the details https://stackoverflow.com/a/6918131/6116637
protected override void Onmanipulationboundaryfeedback (Manipulationboundaryfeedbackeventargs e)
{
}
Modified code: WPF ScrollView Code interpretation 1.2-csdn Download
Then in the mouse scrolling is how to receive scrolling.
From Microsoft source code can see ScrollViewer inherit ContentControl, so can rewrite OnMouseWheel, please see his code
protected override void OnMouseWheel (MouseWheelEventArgs e)
{
if (e.handled) {return;}
if (! handlesmousewheelscrolling)
{return
;
}
if (scrollinfo!= null)
{
if (E.delta < 0) {Scrollinfo.mousewheeldown ();}
else {Scrollinfo.mousewheelup ();}
}
E.handled = true;
}
In fact ScrollViewer is not done scrolling, the actual scrolling is scrollinfo scrolling. Scrollinfo
So what is scrollinfo, in fact he is an interface, the controls placed inside ScrollViewer are not actually placed directly in ScrollViewer, controls are placed in Scrollcontentpresenter, and Scrollcontentpresenter is written in ScrollViewer's Style, and you can see this code in ScrollViewer.
[Templatepart (Name = "Part_scrollcontentpresenter", Type = typeof (Scrollcontentpresenter))]
But from the spam Microsoft code can see, no attributes directly use this, but in the use of the place to write Gettemplatechild (Scrollcontentpresentertemplatename) as Scrollcontentpresenter;
The performance of this writing is relatively poor.
So how did he assign scrollinfo to the value. In fact, the hookupscrollingcomponents of this class is to assign a value to Scrollinfo, where the hookupscrollingcomponents call is onapplytemplate so you can see that The control is already known at the time of initialization.
From the garbage Microsoft source code can see Hookupscrollingcomponents logic, first of all is to judge the attribute Cancontentscroll determine whether the control in the element can scroll, if the control in the element can scroll, Then judge the elements in the control is not inherited iscrollinfo if it is, well, no, the Scrollinfo assignment. If the control inside is not inherited iscrollinfo, then determine if he is in the list, and if so, take the list itemspresenter as Scrollinfo. If still can't get, had to use oneself as Scrollinfo
You can see from here that cancontentscroll if there is no setting, use this class directly, that is, physical scrolling is what this class does. If an element is not in the list and does not inherit iscrollinfo, then even if the setting uses logical scrolling, it is actually a physical scroll. Physical scrolling is the element that does not know how to scroll, and all movement is an element beyond control. Unlike physical scrolling, the logic is that the element controls all scrolling. Physical scrolling
Here's how the physical scrolling is done, and actually scrolling is using the following code in the layout, so that the elements are laid out in the scrolling place, so it looks like the element is scrolling
Rect childrect = new Rect (child. DesiredSize);
if (isscrollclient)
{
childrect.x =-horizontaloffset;
Childrect.y =-verticaloffset;
}
This is needed to stretch to arrange spaces,
childrect.width = Math.max (Childrect.width, Arrangesize.width) ;
Childrect.height = Math.max (Childrect.height, arrangesize.height);
Child. Arrange (childrect);
You can see that the layout setting, in turn, horizontaloffset as an element of x movement, so that the elements can be moved
But if the element is moved outside the ScrollViewer, how to crop it. is actually using the rewrite getlayoutclip for cropping
return new RectangleGeometry (new Rect (rendersize));
From the code can know, in fact, the ScrollViewer is not scrolling elements, scrolling elements are scrollviewer inside the elements, the way to scroll is generally used in the layout of the elements of the X, Y to allow the element to scroll. I looked at the StackPanel and several other classes that were used in this way, because in contrast to Translate, this method does not use Translate and cannot be moved when the user modifies Translate. In addition, this method is done in the layout, direct calculation, if modified Translate also need to be in the layout recalculation, so this method performance will be relatively high. Touch Input
So how does ScrollViewer get input when it comes to touch? In fact, in the touch of the time with the manipulation, in the judgment Panningmode give value
if (Panningmode = = panningmode.horizontalonly)
{
e.mode = Manipulationmodes.translatex;
}
else if (Panningmode = = panningmode.verticalonly)
{
e.mode = Manipulationmodes.translatey;
}
else
{
e.mode = manipulationmodes.translate;
}
So in the Manipulationdelta can get the value of the move, because the direct access to the value is the user's desired path so direct settings do not need to calculate
But need multiple panningratio, if need inertia, then only need to set inertia can.
Probably the whole source code only these, a lot of code is in the judgment boundary, and processing some user input.
At the touch, the core code is manipulatescroll, passing in the current mobile and cumulative movement, moving horizontally. You can do this by determining whether the current move is moving and multiplying it by multiples, and then by setting the values of the HorizontalOffset properties.
So all the code is actually to get input, and then pass it to the corresponding scrollinfo, through the scrollinfo implementation of the method to do the specific business.
But ScrollViewer is not directly incoming scrollinfo needs to be moved, and the command is sent
public void Scrolltohorizontaloffset (double offset)
{
double validatedoffset = Scrollcontentpresenter.validateinputoffset (offset, "offset");
Queue up the scroll command, which tells the content to scroll.
'll leads to a update of all offsets (both live and deferred).
Enqueuecommand (Commands.sethorizontaloffset, validatedoffset, null);
}
Then in the specific function Executenextcommand take out a command to move
private bool Executenextcommand ()
{
iscrollinfo isi = scrollinfo;
Command cmd = _queue. Fetch ();
Switch (cmd. Code)
{case
commands.lineup: ISI. Lineup (); break;
Case Commands.linedown: ISI. LineDown (); break;
Case Commands.lineleft: ISI. Lineleft (); break;
Case Commands.LineRight:isi. Lineright (); break;
Remove the same Code case
Commands.Invalid:return false;
return true;
}
Input may be entered too quickly, and the layout is not immediately layout, from the code can see that the mobile business is in the layout of the modified value, but the layout modification is not a high priority, but the input priority is very high, may be in the layout of the process will be continuously entered. So you need to put the input commands into, using a function to take out the different command processing, and finally layout.
See:
Smooth scrolling in WPF-the blog Park
IScrollInfo in Avalon part I–bencon ' s WebLog
IScrollInfo in Avalon part Ii–bencon ' s WebLog
IScrollInfo in Avalon part Iii–bencon ' s WebLog
IScrollInfo Tutorial Part Iv–bencon ' s WebLog Other source code Analysis
. NET Framework Source code · ScrollViewer
. NET source Analysis –list-Brooks-Blog Park
One-Stop wpf– dependency property (DependencyProperty) One-Zhou Yonghen-Blog Park
I built my own blog https://lindexi.gitee.io/welcome you to visit, there are a lot of new blogs. Only when I read the blog is mature will be placed in the CSDN or blog park, but once released will not be updated
If you see any in the blog do not understand, welcome to exchange, I set up the dotnet vocational and Technical College Welcome to join
This work is licensed with the knowledge sharing signature-non-commercial use-sharing 4.0 International license agreement in the same way. Welcome to reprint, use, republish, but be sure to keep the article signed Lindesi (including Links: HTTP://BLOG.CSDN.NET/LINDEXI_GD), not for commercial purposes, based on the modified work of this article must be issued with the same license. If you have any questions, please contact me.