91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何正確的使用ListView

發布時間:2021-04-02 17:17:23 來源:億速云 閱讀:230 作者:Leah 欄目:編程語言

這篇文章給大家介紹如何正確的使用ListView,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

一、獲取、設置 ListView 的滾動位置

關于獲取、設置 ListView 的滾動位置,微軟已經提供了相關的例子,我在這個 Demo 中是直接套用的。這個功能主要是通過 ListViewPersistenceHelper 來實現的,它提供以下兩個方法:

//獲取 ListView 的滾動位置
public static string GetRelativeScrollPosition(ListViewBase listViewBase, ListViewItemToKeyHandler itemToKeyHandler)

// 設置 ListView 的滾動位置
public static IAsyncAction SetRelativeScrollPositionAsync(ListViewBase listViewBase, String relativeScrollPosition, ListViewKeyToItemHandler keyToItemHandler)

這兩個方法中各有一個參考是委托類型,分別是ListViewItemToKeyHandler 和 ListViewKeyToItemHandler,它們的作用是告訴這個類如何處理列表項與 Key 的對應關系,好使得該類可以正確地獲取或設置滾動位置。這里的 Key 是 ListViewItem 所代表的項目的一個屬性(比如 Demo 中 Item 類的 Id 屬性),這個屬性的值在整個列表中是唯一的;而 Item 是在 Item 對象本身。在 Demo 中它們的實現分別如下:

 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);
  }

實現這兩個方法后,重載列表頁的  OnNavigatingFrom 方法,在其中加入以下代碼,來實現獲取滾動位置并保存:

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

繼續為頁面注冊 Loaded 事件,在 Loaded 事件中加入以下代碼來實現設置滾動位置:

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

這里需要注意的是,設置滾動位置的方法是異步的,所以 Loaded 方法需要加上 async 修飾符。而上述代碼中對 navigationParameter 參數的判斷則是為了區別:在導航時是否定位到最近瀏覽的位置,具體可參考 Demo 的代碼。

二、獲取 ListView 滾動位置處的項目

關于第二個需求的實現,我們首先需要明白以下三點:

  • ListView 的模板 (Template) 中包括 ScrollViewer,我們可以通過 VisualTreeHelper 獲取到此控件;

  • ListView 提供 ContainerFromItem 方法,它使們可以通過傳遞 Item 獲取包括此 Item 的 Container,即 ListViewItem;

  • UIElement 提供 TransformToVisual 方法,可以得到某控件相對指定控件的位置轉換信息;

所以我們的思路就是:得到 ListView 控件中的 ScrollViewer,并遍歷 ListView 中所有的 Item,在遍歷過程中,得到每一項目的 ListViewItem,并判斷它的位置是否位于 ScrollViewer 的位置中。以下是獲取 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;
  }

在上述代碼的 foreach 循環中的部分,正是我們前述思路的體現。而其中所調用的 IsVisibleToUser 方法,則是如何判斷某一 ListViewItem 是否在 ScrollViewer 中為當前可見。其代碼如下:

/// <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);
   }
  }

可以看出,我們是能過得到兩個 Rect 值。Rect 類型的值代表一個矩形區域的位置和大小,我們對這兩個值進行比較后,返回最終的結果。

獲取 ListViewItem 的 Rect 值: element.TransformToVisual(container) 返回的結果是 GeneralTransform 類型,這個值表明了 ListViewItem 相對于 Container(即 ScrollViewer)的位置轉換信息。GeneralTransform 類型可能我們并不太熟悉,不過,從它派生出來的這些類: ScaleTransform、TranslateTransform ,我們就熟悉了,GeneralTransform 正是它們的基類。GeneralTransform 包括以下兩個重要的方法:

  • TransformPoint, 可以將得到的轉換信息計算成 Point 值,表示某控件相對于另一控件的坐標位置

  • TransformBounds,可以將得到的轉換信息計算成 Rect 值,表示某控件相對于另一控件的坐標位置及所占的區域。

所以,我們通過 TransformBounds 方法就得到了 ListViewItem 相對于 ScrollViewer 的位置和所占區域的信息。

獲取 ScrollViewer 的 Rect 值: 直接實例化一個 Rect,以 0,0 作為你左上角的坐標位置點, ScrollViewer 的 ActualWidth 和 ActualHeight 作為其大小。

接下來,就是比較的過程:這里,我們做了一個判斷,判斷是否要求元素 (ListViewItem) 完全在 ScrollViewer 中(而非僅部分在其中)。如果要求部分顯示即可,則只要元素的 Top 小于 Container 的 Bottom 值,并且元素的 Bottom 大于 Container 的 Top;如果要求全部顯示,那么算法是:元素的 Top 大于 Container 的 Top 并且元素的 Bottom 小于 Container 的 Bottom。如果您對語言描述或者代碼都還不明白,也可以在紙上畫一下進行比較。

接下來,我們照著 GetAllVisbleItems 方法的思路可以實現 GetFirstVisibleItem 方法,即獲取列表中第一個可見項,代碼可參考 Demo 的源碼,在此不再贅述。

我們在之前重載的方法 OnNavigatingFrom 中加上這句代碼,即可以獲取到用戶瀏覽位置處的那一項。

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

關于如何正確的使用ListView就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

杭锦旗| 怀仁县| 海南省| 冀州市| 土默特左旗| 偏关县| 陵水| 瓮安县| 寿光市| 湘乡市| 友谊县| 和田市| 山东省| 内江市| 临猗县| 营口市| 无为县| 台前县| 龙门县| 哈密市| 合作市| 治多县| 福泉市| 上饶市| 石城县| 明水县| 南阳市| 沽源县| 特克斯县| 福贡县| 旌德县| 青冈县| 张家川| 阜阳市| 图们市| 南涧| 辉县市| 科尔| 枝江市| 东乡| 突泉县|