ListView 용법 에서 스크롤 과 관련 된 수요 실현

10238 단어 ListView굴러가다
앱 개발 과정 에서 ListView 컨트롤 은 비교적 자주 사용 하 는 컨트롤 중의 하나 이다.그것 의 용법 을 파악 하면 우리 가 어느 정도 개발 효율 을 높 일 수 있다.본 고 는 ListView 의 용법 인 ListView 의 스크롤 위 치 를 가 져 오고 설정 하 며 스크롤 위 치 를 가 져 오 는 항목 을 소개 할 것 이다.여기 서 한 마디 더 하 자 면,이 묘사 가 좀 있 기 때문에,본문의 제목 은 정말 쓰기 어렵다.
예 를 들 어 개발 중인 애플 리 케 이 션 에 이러한 수요 가 있다 면 사용자 가 목록 페이지(ListView 컨트롤 포함)에서 이전 페이지 로 돌아 갈 때 사용자 가 ListView 의 내용 을 어느 위치 와 어느 항목 으로 탐색 하고 있 는 지 알려 주 고 최근 탐색 항목 을 다시 열 수 있 도록 해 야 합 니 다.마지막 으로 탐색 한 위치 에서 계속 탐색 합 니 다.다음 그림:

본 고 는 상술 한 수 요 를 실현 하 는 방법 을 소개 하 였 다.구체 적 으로 말 하면 이 수 요 는 두 가지 작은 수요 로 나 눌 수 있다.즉,
  • ListView 의 스크롤 위 치 를 가 져 오고 설정 합 니 다.
  • ListView 스크롤 위치 에 있 는 항목 을 가 져 옵 니 다.
  • 다음은 위의 그림 에 있 는 데모 응용 프로그램 을 통 해 하나씩 설명 하 겠 습 니 다.(본문 끝 에 원본 다운로드 링크 가 있 습 니 다)이 Demo 는 두 페이지,한 홈 페이지(MainPage),한 목록 페이지(ItemsPage)를 포함 합 니 다.홈 페이지 에 포함:
    단추:Items Page 로 탐색 할 수 있 습 니 다.
    최근 탐색 정보 영역:마지막 으로 탐색 한 항목 을 볼 수 있 고 목록 페이지 에서 마지막 으로 탐색 한 항목 으로 탐색 할 수 있 는 단 추 를 제공 합 니 다.
    목록 페이지 는 ListView 컨트롤 을 포함 하여 여러 항목 을 보 여 줍 니 다.
    1.ListView 의 스크롤 위 치 를 가 져 오고 설정 합 니 다.
    ListView 의 스크롤 위 치 를 가 져 오고 설정 하 는 것 에 대해 마이크로 소프트 는 관련 예 을 제 공 했 습 니 다.저 는 이 데모 에서 직접 사 용 했 습 니 다.이 기능 은 주로 ListViewPersistenceHelper 을 통 해 이 루어 진 것 으로 다음 과 같은 두 가지 방법 을 제공한다.
    
    //   ListView      
    public static string GetRelativeScrollPosition(ListViewBase listViewBase, ListViewItemToKeyHandler itemToKeyHandler)
    
    //    ListView      
    public static IAsyncAction SetRelativeScrollPositionAsync(ListViewBase listViewBase, String relativeScrollPosition, ListViewKeyToItemHandler keyToItemHandler)
    
    이 두 가지 방법 중 하 나 는 의뢰 유형 으로 각각 ListViewItemToKeyHandlerListViewKeyToItemHandler 이다.이들 의 역할 은 목록 항목 과 Key 의 대응 관 계 를 어떻게 처리 하 는 지 알려 주 고 이 유형 이 스크롤 위 치 를 정확하게 얻 거나 설정 할 수 있 도록 하 는 것 이다.여기 서 Key 는 ListView Item 이 대표 하 는 항목 의 속성(예 를 들 어 Demo 에서 Item 류 의 Id 속성)입 니 다.이 속성의 값 은 전체 목록 에서 유일 합 니 다.아 이 템 은 아 이 템 대상 자체 에 있 습 니 다.데모 에서 그들의 실현 은 다음 과 같다.
    
     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 수식 자 를 추가 해 야 합 니 다.상기 코드 에서 navigation Parameter 파라미터 에 대한 판단 은 네 비게 이 션 을 할 때 최근 에 탐색 한 위치 로 위 치 를 정 했 는 지,Demo 의 코드 를 구체 적 으로 참고 할 수 있 습 니 다.
    2.ListView 스크롤 위치 항목 가 져 오기
    두 번 째 수요 의 실현 에 대해 우 리 는 먼저 다음 과 같은 세 가 지 를 알 아야 한다.
  • ListView 의 템 플 릿(Template)에는 ScrollViewer 가 포함 되 어 있 습 니 다.VisualTreeHelper 를 통 해 이 컨트롤 을 가 져 올 수 있 습 니 다.
  • ListView 는 Container FromItem 방법 을 제공 하여 이 Item 을 포함 한 Container,즉 ListView Item 을 전달 할 수 있 도록 합 니 다.
  • UIElement 는 TransformToVisual 방법 을 제공 하여 특정한 컨트롤 이 상대 적 으로 지정 한 컨트롤 의 위치 변환 정 보 를 얻 을 수 있 습 니 다.
  • 그래서 우리 의 생각 은 ListView 컨트롤 에 있 는 ScrollViewer 를 얻 고 ListView 에 있 는 모든 Item 을 옮 겨 다 니 며 모든 항목 의 ListView Item 을 얻 고 그 위치 가 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 방법 은 특정한 ListView Item 이 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 유형의 값 은 직사각형 구역 의 위치 와 크기 를 대표 합 니 다.우 리 는 이 두 값 을 비교 한 후에 최종 결 과 를 되 돌려 줍 니 다.
    ListView Item 의 Rect 값 을 가 져 옵 니 다:element.TransformToVisual(container)이 돌아 온 결 과 는 GeneralTransform 형식 입 니 다.이 값 은 ListView Item 이 Container(즉 ScrollViewer)의 위치 변환 정 보 를 나 타 냅 니 다.GeneralTransform 유형 은 우리 가 잘 모 르 겠 지만,그것 에서 파생 된 이러한 유형:Scale Transform,Translate Transform,우 리 는 잘 알 고 있 습 니 다.GeneralTransform 은 바로 그들의 기본 클래스 입 니 다.General Transform 은 다음 과 같은 두 가지 중요 한 방법 을 포함한다.
  • TransformPoint 는 얻 은 변환 정 보 를 Point 값 으로 계산 하여 특정한 컨트롤 이 다른 컨트롤 의 좌표 위치 에 비해
  • 을 나타 낸다.
  • TransformBounds 는 변 환 된 정 보 를 Rect 값 으로 계산 하여 특정한 컨트롤 이 다른 컨트롤 의 좌표 위치 와 차지 하 는 구역 을 나타 낸다.
  • 그래서 저 희 는 TransformBounds 방법 을 통 해 ListView Item 이 ScrollViewer 의 위치 와 차지 하 는 지역 에 대한 정 보 를 얻 었 습 니 다.
    ScrollViewer 의 Rect 값 가 져 오기:Rect 를 직접 예화 합 니 다.0,0 을 왼쪽 상단 의 좌표 위치 로 하고 ScrollViewer 의 ActualWidth 와 ActualHeight 를 크기 로 합 니 다.
    다음은 비교 과정 이다.여기 서 우 리 는 요소(ListView Item)가 부분 만 있 는 것 이 아니 라 스크롤 뷰 어 에 있 는 지 판단 했다.부분 적 인 표 시 를 요구 하면 요소 의 Top 이 Container 의 Bottom 값 보다 적 고 요소 의 Bottom 이 Container 의 Top 보다 크다.모든 디 스 플레이 를 요구 하면 알고리즘 은 요소 의 Top 이 Container 의 Top 보다 크 고 요소 의 Bottom 이 Container 의 Bottom 보다 작 습 니 다.언어 설명 이나 코드 를 아직 모 르 시 면 종이 에 그 려 서 비교 하 셔 도 됩 니 다.
    그 다음 에 우 리 는 GetAllVisbleItems 방법의 사고방식 에 따라 GetFirst Visible Item 방법 을 실현 할 수 있 습 니 다.즉,목록 에서 첫 번 째 로 볼 수 있 는 항목 을 얻 을 수 있 습 니 다.코드 는 Demo 의 원본 코드 를 참고 할 수 있 습 니 다.여기 서 더 이상 군말 하지 않 겠 습 니 다.
    이전에 다시 불 러 오 는 방법 인 OnNavigatingFrom 에 이 코드 를 추가 하면 사용자 가 위 치 를 탐색 하 는 곳 에 있 는 것 을 얻 을 수 있 습 니 다.
    
    var targetItem = this.listView.GetFirstVisibleItem<Item>();
    이로써 모든 주요 기능 이 기본적으로 완성 되 었 다.
    결어
    본 고 는 ListView 의 스크롤 위 치 를 어떻게 얻 고 설정 하 는 지,그리고 스크롤 위 치 를 가 져 오 는 지 를 소개 했다.전 자 는 주로 ListView PersistenceHelper 를 통 해 이 루어 졌 고 후 자 는 ListView Item 과 ScrollViewer 의 Rect 값 을 얻 고 비교 한 결과 실 현 된 것 이다.더 좋 은 방법,다른 것 을 볼 수 있다 면 메 시 지 를 남기 고 함께 교류 하 세 요.
    원본 코드 다운로드
    참고 자료:
    ListView Sample
    How to get the first visible group key in the grouped listview
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기