UWP: Implementation of two requirements related to scrolling in ListView, uwplistview

Source: Internet
Author: User

UWP: Implementation of two requirements related to scrolling in ListView, uwplistview

During App development, the ListView control is one of the commonly used controls. Understanding its usage can help us improve development efficiency to a certain extent. This article will introduce a usage of ListView --Obtain and set the scroll position of the ListView and the items at the scroll position.The title of this article is not very good because of this description.

For example, if the application you are developing has such a requirement, when the user returns from a list page (including the ListView Control) to the previous page, you need to obtain the location and item where the user browses the content in the ListView, so as to inform the user of the recent browsing items and allow the user to open the list again, continue browsing from the last browsing position. For example:

This article describes how to implement the above requirements. Specifically, this requirement can be divided into two small demands:

Below I will explain it one by one through the Demo Application shown in the figure above (the source code download link is available at the end of this article). This Demo includes two pages, one home page (MainPage) and one list page (ItemsPage ). The home page includes:

  • Button: you can navigate to ItemsPage;
  • Recently browsed information area: You can view the last browsed project and provide a button to navigate to the last browsed project on the list page;

The list page contains a ListView control that displays several items.

1. Obtain and set the scroll position of the ListView

Microsoft has provided related examples for obtaining and setting the scroll position of the ListView. I applied it directly in this Demo. This function is implemented through ListViewPersistenceHelper. It provides the following two methods:

// Obtain the public static string GetRelativeScrollPosition (ListViewBase listViewBase, ListViewItemToKeyHandler itemToKeyHandler) of the ListView)
// Set the rolling position of the ListView public static IAsyncAction SetRelativeScrollPositionAsync (ListViewBase listViewBase, String relativeScrollPosition, ListViewKeyToItemHandler keyToItemHandler)

Each of these two methods has a reference of the delegate type, which is ListViewItemToKeyHandler and ListViewKeyToItemHandler. Their role is to tell this class how to handle the ing between list items and keys, so that the class can correctly obtain or set the scroll position. The Key here is an attribute of the project represented by ListViewItem (for example, the Id attribute of the Item class in Demo). The value of this attribute is unique throughout the list; the Item is in the Item object itself. In the Demo, their implementations are as follows:

        private string ItemToKeyHandler(object item)        {            Item dataItem = item as Item;            if (dataItem == null) return null;            return dataItem.Id.ToString();        }        private IAsyncOperation<object> KeyToItemHandler(string key)        {            Func<System.Threading.CancellationToken, Task<object>> taskProvider = token =>            {                var items = listView.ItemsSource as List<Item>;                if (items != null)                {                    var targetItem = items.FirstOrDefault(m => m.Id == int.Parse(key));                    return Task.FromResult((object)targetItem);                }                else                {                    return Task.FromResult((object)null);                }            };            return AsyncInfo.Run(taskProvider);        }

After the two methods are implemented, reload the OnNavigatingFrom method on the list page and add the following code to obtain the scroll position and save it:

           string position = ListViewPersistenceHelper.GetRelativeScrollPosition(this.listView, ItemToKeyHandler);           NavigationInfoHelper.SetInfo(targetItem, position);

Register the Loaded event for the page. Add the following code to the Loaded event to set the scroll position:

            if (navigationParameter != null)            {                if (NavigationInfoHelper.IsHasInfo)                {                    await ListViewPersistenceHelper.SetRelativeScrollPositionAsync(listView, NavigationInfoHelper.LastPosition, KeyToItemHandler);                }            }

Note that the method for setting the scroll position is asynchronous, so the async modifier must be added to the Loaded method. In the preceding code, the navigationParameter parameter is determined to distinguish whether to locate the recently viewed location during navigation. For details, refer to the Demo code.

2. Get the items at the scroll position of the ListView

For the implementation of the second requirement, we must first understand the following three points:

So our idea is: Get the ScrollViewer in the ListView control, traverse all items in the ListView, and get the ListViewItem for each Item during the traversal process, and determine whether it is in the position of ScrollViewer. The following code Retrieves all visible items in the ListView:

        public static List<T> GetAllVisibleItems<T>(this ListViewBase listView)        {            var scrollViewer = listView.GetScrollViewer();            if (scrollViewer == null)            {                return null;            }            List<T> targetItems = new List<T>();            foreach (T item in listView.Items)            {                var itemContainer = listView.ContainerFromItem(item) as FrameworkElement;                bool isVisible = IsVisibileToUser(itemContainer, scrollViewer, true);                if (isVisible)                {                    targetItems.Add(item);                }            }            return targetItems;        }

In the foreach loop of the above Code, it is the embodiment of our above ideas. The IsVisibleToUser method is called to determine whether a ListViewItem is visible in ScrollViewer. The Code is as follows:

        /// <summary>        /// Code from here:        ///  https://social.msdn.microsoft.com/Forums/en-US/86ccf7a1-5481-4a59-9db2-34ebc760058a/uwphow-to-get-the-first-visible-group-key-in-the-grouped-listview?forum=wpdevelop        /// </summary>        /// <param name="element">ListViewItem or element in ListViewItem</param>        /// <param name="container">ScrollViewer</param>        /// <param name="isTotallyVisible">If the element is partially visible, then include it. The default value is false</param>        /// <returns>Get the visibility of the target element</returns>        private static bool IsVisibileToUser(FrameworkElement element, FrameworkElement container, bool isTotallyVisible = false)        {            if (element == null || container == null)                return false;            if (element.Visibility != Visibility.Visible)                return false;            Rect elementBounds = element.TransformToVisual(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));            Rect containerBounds = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);            if (!isTotallyVisible)            {                return (elementBounds.Top < containerBounds.Bottom && elementBounds.Bottom > containerBounds.Top);            }            else            {                return (elementBounds.Bottom < containerBounds.Bottom && elementBounds.Top > containerBounds.Top);            }        }

We can see that we can get two Rect values. The value of the Rect type represents the position and size of a rectangle. After comparing the two values, the final result is returned.
Obtains the Rect value of ListViewItem.: The result returned by element. TransformToVisual (container) is of the GeneralTransform type. This value indicates the location conversion information between ListViewItem and Container (that is, ScrollViewer. We are not familiar with the GeneralTransform type, but we are familiar with the classes derived from it: ScaleTransform and TranslateTransform. GeneralTransform is their base class. GeneralTransform includes the following two important methods:

Therefore, we use the TransformBounds method to obtain the location and region of ListViewItem relative to ScrollViewer.
Obtain the Rect value of ScrollViewer.: Directly instantiate a Rect, with 0, 0 as the Coordinate Position point in the upper left corner, and ActualWidth and ActualHeight of ScrollViewer as the size.

Next, we will make a comparison process: Here, we make a judgment to determine whether the elements (ListViewItem) are completely in the ScrollViewer (not only in part ). If partial display is required, the algorithm is: the Top of the element is greater than the Top of the iner, and the Bottom of the element is smaller than the Bottom of the Container. If you do not understand the language description or code, you can also draw a comparison on the paper.

Next, we can use the GetAllVisbleItems method to implement the GetFirstVisibleItem method, that is, to obtain the first visible item in the list. The code can refer to the Demo source code and will not be repeated here.

We added this code to the previously overloaded method OnNavigatingFrom to obtain the item at the user's browsing location.

          var targetItem = this.listView.GetFirstVisibleItem<Item>();

So far, all the main functions have been basically completed.

 

Conclusion

This article describes how to obtain and set the scroll position of the ListView and obtain the scroll position. The former is mainly implemented by ListViewPersistenceHelper, the latter is implemented by obtaining and comparing the Rect values of ListViewItem and ScrollViewer. If you have a better way to see different things, please leave a message and communicate with each other.

 

Source code download

References:

ListView Sample
How to get the first visible group key in the grouped listview

Related Article

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.