. NET Framework Source code · ScrollViewer

Source: Internet
Author: User
Tags creative commons attribution

This article is an analysis of the. NET Framework source code series, mainly to tell you Microsoft to do ScrollViewer ideas, analysis is very simple

After reading this article, you can learn how to write a ScrollViewer, how to define a iscrollinfo or to give him a scroll to add animation

Use

The following shows you how to use the ScrollViewer, generally in the need to scroll the outside of the control to put a ScrollViewer to achieve scrolling.

  <ScrollViewer HorizontalScrollBarVisibility="Auto">    <StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">      <TextBlock TextWrapping="Wrap" Margin="0,0,0,20">Scrolling is enabled when it is necessary.       Resize the window, making it larger and smaller.</TextBlock>      <Rectangle Fill="Red" Width="500" Height="500"></Rectangle>    </StackPanel>  </ScrollViewer>

But not all controls can be scrolled out of place with a ScrollViewer, because scrolling actually requires the control to do it by itself.

Principle

Let's show you how scrolling is done.

One of the simplest ways to do this is to set the element to transForm.Y scroll in this way is the simplest way, but the downside is that other controls cannot do other moves.

In ScrollViewer there are two scrolling modes, physical scrolling and logical scrolling, and if you use physical scrolling then scrolling is ScrollViewer done, and how to use logical scrolling, then scrolling is what the control does.

So I'll start with the ScrollViewer receive input.

Input

If you use ScrollViewer to scroll, you may encounter a magical need to scroll through the touch. Yes, if using a simple ScrollViewer is unable to use touch scrolling

Please look at the code, write a simple ScrollViewer inside 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 colors 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 = 20,                    Fill = (Brush)temp                };                HcrkKmqnnfzo.Children.Add(rectangle);            }        }

Code: WPF ScrollView Code explanation 1.1-csdn Download

If you don't have csdn points, try using my network, but if my network is out of date, please let me know.

If you need to use scrolling in touch, then you need to set up to PanningMode support vertical dragging.

If this is set PanningMode , you will find that dragging the window jitter, when you need to rewrite onmanipulationboundaryfeedback in the window, see the code below. Do not write anything in the function, see https://stackoverflow.com/a/6918131/6116637 for details

       protected override void OnManipulationBoundaryFeedback(ManipulationBoundaryFeedbackEventArgs e)        {        }

Modified code: WPF ScrollView Code explanation 1.2-csdn Download

So how does the mouse scroll to receive scrolling?

From the Microsoft source code can see ScrollViewer inherit ContentControl, so can rewrite OnMouseWheel, 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 doing scrolling, the actual scrolling is ScrollInfo scrolling.

ScrollInfo

So what is ScrollInfo, actually he is an interface, the controls placed inside the ScrollViewer are not actually placed directly in the ScrollViewer, the control is placed ScrollContentPresenter , and the Scrollcontentpresenter is written in In ScrollViewer's Style, this code can be seen in ScrollViewer

[TemplatePart(Name = "PART_ScrollContentPresenter", Type = typeof(ScrollContentPresenter))]

But from the garbage Microsoft code can be seen, no attributes directly use this, but in the use of the place to writeGetTemplateChild(ScrollContentPresenterTemplateName) as ScrollContentPresenter;

The performance of this write is relatively poor.

So how did he assign ScrollInfo? In fact, the hookupscrollingcomponents of this class is to assign values to ScrollInfo, where hookupscrollingcomponents is called 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, the first is to determine whether the properties CanContentScroll of the element control can scroll, if the elements of the control can be scrolled, then determine whether the elements of the control is not inherited IScrollInfo if so, um , no, I will assign the ScrollInfo. If the control inside is not inherited IScrollInfo , then determine if he is in the list, and if so, take the list ItemsPresenter as a scrollinfo. If you still can't get it, you have to use yourself asScrollInfo

From here you can see that cancontentscroll, if not set, uses 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 where elements do not know scrolling, and all movements are elements that cannot be controlled. Unlike physical scrolling, the logic is that the element controls all scrolling.

Physical scrolling

Let's tell you how physical scrolling is done, actually scrolling is using the following code in the layout so that the elements are laid out in a scrolling place, so it looks like the element scrolls

                  Rect childRect = new Rect(child.DesiredSize);                         if (IsScrollClient)                        {                            childRect.X = -HorizontalOffset;                            childRect.Y = -VerticalOffset;                        }                         //this is needed to stretch the child to arrange space,                        childRect.Width = Math.Max(childRect.Width, arrangeSize.Width);                        childRect.Height = Math.Max(childRect.Height, arrangeSize.Height);                         child.Arrange(childRect);

You can see the layout setting in turn HorizontalOffset as the x movement of the element, so that the element can be moved

But if the elements move outside the ScrollViewer, how do they crop? is actually using the rewrite getlayoutclip to crop

 return new RectangleGeometry(new Rect(RenderSize));

From the code can be known, the actual ScrollViewer is not scrolling elements, scrolling element is the element inside the ScrollViewer, scrolling is generally used in the layout of the element to set the X, Y to let the element scroll. I looked at StackPanel and several other classes, all in this way, because the way to compare Translate, this method will not be used Translate will not be able to move when the user modifies Translate. In addition, this method is done in the layout, direct calculation, if the modification of Translate also need to be recalculated in the layout, so the performance of this method will be relatively high.

Touch input

So how does ScrollViewer get input when it touches? In fact, in the touch of the use of manipulation, in judging panningmode to the value

                    if (panningMode == PanningMode.HorizontalOnly)                    {                        e.Mode = ManipulationModes.TranslateX;                    }                    else if (panningMode == PanningMode.VerticalOnly)                    {                        e.Mode = ManipulationModes.TranslateY;                    }                    else                    {                        e.Mode = ManipulationModes.Translate;                    }

So the Manipulationdelta can get the moving value, because the direct value is the path that the user wants, so the direct setting does not need to calculate

But need multiples panningratio, if need inertia, then only need to set inertia to be able.

Probably the entire source code only these, a lot of code is to judge the boundary, but also to handle some user input.

In the touch, the core code is manipulatescroll, passing in the current movement and accumulation of movement, whether the horizontal movement. Re-layout is possible by judging whether the current movement has moved and multiplied by multiples, and then by setting the values of the HorizontalOffset properties.

So all the code is actually getting input, and then passing it to the corresponding ScrollInfo, and doing the specific business through the ScrollInfo implementation method.

However, ScrollViewer is not passed directly into the ScrollInfo need to be moved, and the Send command

             public void ScrollToHorizontalOffset(double offset)        {            double validatedOffset = ScrollContentPresenter.ValidateInputOffset(offset, "offset");             // Queue up the scroll command, which tells the content to scroll.            // Will lead to an 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;                //去掉差不多的代码                case Commands.Invalid: return false;            }            return true;        }

Input may be entered too quickly, and layout is not immediately layout, from the code can be seen, the mobile business is in the layout to modify the value, but the layout changes are not high priority, but the priority of the input is very high, may be in the layout of the process is entered. So we need to put the input command, use a function to take out each, the different command processing, and finally layout.

See:

Implementing smooth Scrolling in WPF-the Horizon-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 Code Analysis –list

One-stop-wpf--dependency properties (DependencyProperty)-Zhou Yonghen-Blog Park

I set up my own blog https://lindexi.gitee.io/welcome everyone to visit, there are many new blog. Only when I see the blog is mature will not be placed in the CSDN or blog park, but once published, no longer update

If you see anything in the blog do not understand, welcome to communicate, I set up the Dotnet Vocational Technical College welcome everyone to join


This work is licensed under the Creative Commons Attribution-NonCommercial use-Share 4.0 International license agreement in the same way. Welcome to reprint, use, republish, but be sure to keep the article Attribution Lindesi (including Link: http://blog.csdn.net/lindexi_gd), not for commercial purposes, based on the modified works of this article must be issued with the same license. If you have any questions, please contact me.

. NET Framework Source code · ScrollViewer

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.