ListView 및 GridView 데이터 가상화ListView and GridView data virtualization

참고  자세한 내용은 //build/ 세션 사용자가 GridView 및 ListView에서 많은 데이터를 조작할 때의 획기적인 성능 향상을 참조하세요.Note  For more details, see the //build/ session Dramatically Increase Performance when Users Interact with Large Amounts of Data in GridView and ListView.

데이터 가상화를 통해 ListViewGridView 성능과 시작 시간이 향상됩니다.Improve ListView and GridView performance and startup time through data virtualization. UI 가상화, 요소 감소 및 항목의 점진적인 업데이트를 보려면 ListView 및 GridView UI 최적화를 참조하세요.For UI virtualization, element reduction, and progressive updating of items, see ListView and GridView UI optimization.

데이터 가상화 방법은 너무 커서 메모리에 한 번에 저장할 수 없거나 저장해서는 안 되는 데이터 집합에 필요합니다.A method of data virtualization is needed for a data set that is so large that it cannot or should not all be stored in memory at one time. 초기 부분을 메모리에 로드(로컬 디스크, 네트워크 또는 클라우드)하고 이 부분 데이터 집합에 UI 가상화를 적용합니다.You load an initial portion into memory (from local disk, network, or cloud) and apply UI virtualization to this partial data set. 나중에 데이터를 증분식으로 로드하거나 필요에 따라 마스터 데이터 집합의 임의 지점(임의 액세스)에서 로드할 수 있습니다.You can later load data incrementally, or from arbitrary points in the master data set (random access), on demand. 데이터 가상화가 적합한지 여부는 여러 요인에 따라 달라집니다.Whether data virtualization is appropriate for you depends on many factors.

  • 데이터 집합의 크기The size of your data set
  • 각 항목의 크기The size of each item
  • 데이터 집합의 소스(로컬 디스크, 네트워크 또는 클라우드)The source of the data set (local disk, network, or cloud)
  • 앱의 전체 메모리 소비The overall memory consumption of your app

참고  ListView 및 GridView에서는 사용자가 빠르게 이동/스크롤하는 동안 일시적으로 자리 표시자 시각적 개체를 표시하는 기능이 기본적으로 사용됩니다.Note  Be aware that a feature is enabled by default for ListView and GridView that displays temporary placeholder visuals while the user is panning/scrolling quickly. 데이터가 로드되면 이러한 자리 표시자 화면 효과가 항목 템플릿으로 바뀝니다.As data is loaded, these placeholder visuals are replaced with your item template. ListViewBase.ShowsScrollingPlaceholders를 false로 설정하여 이 기능을 끌 수 있지만 이렇게 하는 경우 x:Phase 특성을 사용하여 항목 템플릿의 요소를 점진적으로 렌더링하는 것이 좋습니다.You can turn the feature off by setting ListViewBase.ShowsScrollingPlaceholders to false, but if you do so then we recommend that you use the x:Phase attribute to progressively render the elements in your item template. 점진적으로 ListView 및 GridView 항목 업데이트를 참조하세요.See Update ListView and GridView items progressively.

증분 및 임의 액세스 데이터 가상화 기술에 대한 자세한 내용은 다음과 같습니다.Here are more details about the incremental and random-access data virtualization techniques.

증분 데이터 가상화Incremental data virtualization

증분 데이터 가상화에서는 데이터가 순차적으로 로드됩니다.Incremental data virtualization loads data sequentially. 증분 데이터 가상화를 사용하는 ListView는 100만 항목의 컬렉션을 보는 데 사용될 수 있지만 초기에는 50개의 항목만 로드됩니다.A ListView that uses incremental data virtualization may be used to view a collection of a million items, but only 50 items are loaded initially. 사용자가 이동/스크롤하면 다음 50개가 로드됩니다.As the user pans/scrolls, the next 50 are loaded. 항목이 로드됨에 따라 스크롤 막대의 위치 조정 컨트롤의 크기가 줄어듭니다.As items are loaded, the scroll bar's thumb decreases in size. 이 데이터 가상화 유형의 경우 이러한 인터페이스를 구현하는 데이터 원본 클래스를 작성합니다.For this type of data virtualization you write a data source class that implements these interfaces.

이와 같은 데이터 원본은 지속적으로 확장될 수 있는 메모리 내 목록입니다.A data source like this is an in-memory list that can be continually extended. 항목 컨트롤은 표준 IList 인덱서 및 개수 속성을 사용하는 항목을 요청합니다.The items control will ask for items using the standard IList indexer and count properties. 개수는 데이터 세트의 실제 크기가 아니라 항목 수를 로컬로 나타내야 합니다.The count should represent the number of items locally, not the true size of the dataset.

항목 컨트롤이 기존 데이터의 끝에 가까워지면 ISupportIncrementalLoading.HasMoreItems를 호출합니다.When the items control gets close to the end of the existing data, it will call ISupportIncrementalLoading.HasMoreItems. true를 반환하면 로드할 권장 항목 수를 전달하는 ISupportIncrementalLoading.LoadMoreItemsAsync를 호출합니다.If you return true, then it will call ISupportIncrementalLoading.LoadMoreItemsAsync passing an advised number of items to load. 데이터를 로드하는 위치(로컬 디스크, 네트워크 또는 클라우드)에 따라 권장 개수와 다른 개수의 항목을 로드하도록 선택할 수 있습니다.Depending on where you're loading data from (local disk, network, or cloud), you may choose to load a different number of items than that advised. 예를 들어 서비스에서 50개 항목의 일괄 처리를 지원하지만 항목 컨트롤에서 10개를 요청하는 경우 50개를 로드할 수 있습니다.For example, if your service supports batches of 50 items but the items control only asks for 10 then you can load 50. 백 엔드에서 데이터를 로드하고 목록에 추가한 후 항목 컨트롤이 새 항목을 인식하도록 INotifyCollectionChanged 또는 IObservableVector<T> 를 통해 변경 알림을 발생시킵니다.Load the data from your back end, add it to your list, and raise a change notification via INotifyCollectionChanged or IObservableVector<T> so that the items control knows about the new items. 또한 실제로 로드한 항목 수를 반환합니다.Also return a count of the items you actually loaded. 권장 개수보다 적은 항목을 로드하거나 항목 컨트롤이 중간에 훨씬 멀리 이동/스크롤된 경우 추가 항목에 대해 데이터 원본가 다시 호출되고 주기가 계속됩니다.If you load fewer items than advised, or the items control has been panned/scrolled even further in the interim, then your data source will be called again for more items and the cycle will continue. Windows 8.1용 XAML 데이터 바인딩 샘플을 다운로드하고 Windows 10 앱에서 해당 소스 코드를 재사용하여 자세히 알아볼 수 있습니다.You can learn more by downloading the XAML data binding sample for Windows 8.1 and re-using its source code in your Windows 10 app.

임의 액세스 데이터 가상화Random access data virtualization

임의 액세스 데이터 가상화에서는 데이터 집합의 임의 지점에서 데이터를 로드할 수 있습니다.Random access data virtualization allows loading from an arbitrary point in the data set. 100만 개의 항목을 보는 데 사용되는 임의 액세스 데이터 가상화를 사용하는 ListView는 100,000~100,050개의 항목을 로드할 수 있습니다.A ListView that uses random access data virtualization, used to view a collection of a million items, can load the items 100,000 – 100,050. 사용자가 목록의 시작 부분으로 이동하면 컨트롤이 1~50개의 항목을 로드합니다.If the user then moves to the beginning of the list, the control loads items 1 – 50. 스크롤 막대의 위치 조정 컨트롤은 항상 ListView에 100만 개의 항목이 포함되어 있음을 나타냅니다.At all times, the scroll bar's thumb indicates that the ListView contains a million items. 스크롤 막대의 위치 조정 컨트롤 위치는 컬렉션의 전체 데이터 집합에서 표시된 항목이 있는 위치를 기준으로 합니다.The position of the scroll bar's thumb is relative to where the visible items are located in the collection's entire data set. 이 유형의 데이터 가상화는 메모리 요구 사항 및 컬렉션 로드 시간을 크게 줄일 수 있습니다.This type of data virtualization can significantly reduce the memory requirements and load times for the collection. 이를 지원하려면 필요에 따라 데이터를 가져오고 로컬 캐시를 관리하며 이러한 인터페이스를 구현하는 데이터 원본 클래스를 작성해야 합니다.To enable it you need to write a data source class that fetches data on demand and manages a local cache and implements these interfaces.

IItemsRangeInfo는 컨트롤에서 자주 사용되는 항목에 대한 정보를 제공합니다.IItemsRangeInfo provides information on which items the control is actively using. 항목 컨트롤은 해당 보기가 변경될 때마다 이 메서드를 호출하며 다음 두 가지 범위 집합을 포함합니다.The items control will call this method whenever its view is changing, and will include these two sets of ranges.

  • 뷰포트에 있는 항목 집합The set of items that are in the viewport.
  • 컨트롤에서 사용하지만 뷰포트에 없을 수 있는 가상화되지 않은 항목 집합A set of non-virtualized items that the control is using that may not be in the viewport.
    • 터치 이동이 원활하도록 항목 컨트롤에서 유지하는 뷰포트 주위의 항목 버퍼A buffer of items around the viewport that the items control keeps so that touch panning is smooth.
    • 포커스가 있는 항목The focused item.
    • 첫 번째 항목The first item.

IItemsRangeInfo를 구현하면 데이터 원본가 가져오고 캐시해야 하는 항목 및 더 이상 필요 없는 캐시 데이터를 정리할 시점을 인식합니다.By implementing IItemsRangeInfo your data source knows what items need to be fetched and cached, and when to prune from the cache data that is no longer needed. IItemsRangeInfo에서는 ItemIndexRange 개체를 사용하여 컬렉션 내 해당 인덱스를 기반으로 항목 집합을 설명합니다.IItemsRangeInfo uses ItemIndexRange objects to describe a set of items based on their index in the collection. 이는 올바르거나 안정적이지 않을 수 있는 항목 포인터를 사용하지 않도록 하기 위한 것입니다.This is so that it doesn't use item pointers, which may not be correct or stable. IItemsRangeInfo는 항목 컨트롤에 대한 상태 정보를 기반으로 하기 때문에 해당 항목 컨트롤의 단일 인스턴스에서만 사용되도록 설계되었습니다.IItemsRangeInfo is designed to be used by only a single instance of an items control because it relies on state information for that items control. 여러 항목 컨트롤이 동일한 데이터에 액세스해야 하는 경우 각각에 대해 별도의 데이터 원본 인스턴스가 필요합니다.If multiple items controls need access to the same data then you will need a separate instance of the data source for each. 여러 항목 컨트롤은 공용 캐시를 공유할 수 있지만 캐시에서 정리하는 논리가 보다 복잡합니다.They can share a common cache, but the logic to purge from the cache will be more complicated.

임의 액세스 데이터 가상화 데이터 원본에 대한 기본 전략은 다음과 같습니다.Here's the basic strategy for your random access data virtualization data source.

  • 항목이 요청될 때When asked for an item
    • 메모리에 사용할 수 있는 경우 해당 항목을 반환합니다.If you have it available in memory, then return it.
    • 해당 항목이 없는 경우 null 또는 자리 표시자 항목을 반환합니다.If you don’t have it, then return either null or a placeholder item.
    • 필요한 항목을 알고 해당 항목에 대한 데이터를 백 엔드에서 비동기식으로 가져오려면 항목에 대한 요청(또는 IItemsRangeInfo의 범위 정보)을 사용합니다.Use the request for an item (or the range information from IItemsRangeInfo) to know which items are needed, and to fetch data for items from your back end asynchronously. 데이터를 검색한 후 항목 컨트롤이 새 항목을 인식하도록 INotifyCollectionChanged 또는 IObservableVector<T> 를 통해 변경 알림을 발생시킵니다.After retrieving the data, raise a change notification via INotifyCollectionChanged or IObservableVector<T> so that the items control knows about the new item.
  • (옵션) 항목 컨트롤의 뷰포트가 변경되면 IItemsRangeInfo의 구현을 통해 데이터 원본에서 필요한 항목을 식별합니다.(Optionally) as the items control's viewport changes, identify what items are needed from your data source via your implementation of IItemsRangeInfo.

이러한 전략 외에 데이터 항목을 로드할 시점, 로드할 개수 및 메모리에서 유지할 항목에 대한 전략은 애플리케이션에 달려 있습니다.Beyond that, the strategy for when to load data items, how many to load, and which items to keep in memory is up to your application. 몇 가지 일반적인 고려 사항은 다음과 같습니다.Some general considerations to keep in mind:

  • 데이터에 대한 비동기 요청을 만듭니다. UI 스레드를 차단하지 마세요.Make asynchronous requests for data; don't block the UI thread.
  • 항목을 가져오는 일괄 처리의 적정한 크기를 확인합니다.Find the sweet spot in the size of the batches you fetch items in. chatty보다 chunky를 기본적으로 사용합니다.Prefer chunky to chatty. 작은 요청이 너무 많이 만들어질 정도로 작게 설정하지 말고, 검색하는 너무 오래 걸릴 정도로 크게 설정하지 마세요.Not so small that you make too many small requests; not too large that they take too long to retrieve.
  • 동시에 보류할 요청 수를 고려합니다.Consider how many requests you want to have pending at the same time. 한 번에 하나씩 수행하는 것이 더 간편하지만 소요 시간이 긴 경우 너무 느릴 수 있습니다.Performing one at a time is easier, but it may be too slow if turnaround time is high.
  • 데이터 요청을 취소할 수 있나요?Can you cancel requests for data?
  • 호스팅 서비스를 사용하는 경우 트랜잭션당 비용이 있나요?If using a hosted service, is there a cost per transaction?
  • 쿼리 결과가 변경된 경우 서비스에서 어떤 종류의 알림이 제공되나요?What kind of notifications are provided by the service when the results of a query are changed? 항목이 인덱스 33에 삽입된 경우 이를 알 수 있나요?Will you know if an item is inserted at index 33? 서비스가 key-plus-offset 기반의 쿼리를 지원하는 경우 인덱스만 사용하는 것보다 더 나을 수 있습니다.If your service supports queries based on a key-plus-offset, that may be better than just using an index.
  • 항목 사전 가져오기가 어느 정도 지능적으로 수행되기를 원하시나요?How smart do you want to be in pre-fetching items? 스크롤 방향 및 속도를 추적하여 필요한 항목을 예측하려고 하시나요?Are you going to try and track the direction and velocity of scrolling to predict which items are needed?
  • 캐시 지우기가 어느 정도 적극적이기를 원하시나요?How aggressive do you want to be in purging the cache? 메모리와 환경 간에 상충 관계가 있습니다.This is a tradeoff of memory versus experience.