Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Not Daha fazla ayrıntı için Bkz. GridView ve ListView'da Kullanıcılar Büyük Miktarlarda Veriyle Etkileşime Geçtiğinde Performansı Önemli Ölçüde Artırma //build/ oturumu.
Ui sanallaştırma, öğe azaltma ve öğelerin aşamalı güncelleştirmesi aracılığıyla ListView ve GridView performansını ve başlangıç süresini geliştirin. Veri sanallaştırma teknikleri için bkz. WinUI için ListView ve GridView veri sanallaştırma.
Koleksiyon performansında iki önemli faktör
Koleksiyonları yönetmek yaygın bir senaryodur. Fotoğraf görüntüleyicide fotoğraf koleksiyonları, okuyucuda makale, kitap veya hikaye koleksiyonları ve alışveriş uygulamasında ürün koleksiyonları bulunur. Bu konu başlığında, Koleksiyonları düzenleme konusunda WinUI uygulamanızı verimli hale getirmek için yapabilecekleriniz gösterilmektedir.
Koleksiyonlar söz konusu olduğunda performansta iki önemli faktör vardır: biri kullanıcı arabirimi iş parçacığının öğe oluşturması için harcanan süredir; diğeri, hem ham veri kümesi hem de bu verileri işlemek için kullanılan kullanıcı arabirimi öğeleri tarafından kullanılan bellektir.
Sorunsuz gezinme ve kaydırma için, kullanıcı arabirimi iş parçacığının öğeleri örnekleme, veri bağlama ve düzenleme konusunda verimli ve akıllı bir şekilde çalışması çok önemlidir.
KULLANıCı arabirimi sanallaştırma
Ui sanallaştırma, yapabileceğiniz en önemli geliştirmedir. Bu, öğeleri temsil eden kullanıcı arabirimi öğelerinin isteğe bağlı olarak oluşturulduğu anlamına gelir. 1000 öğeden oluşan bir koleksiyona bağlı bir öğe denetimi için, tümü aynı anda görüntülenemediğinden, tüm öğelerin kullanıcı arabirimini aynı anda oluşturmak kaynak israfı olur. ListView ve GridView (ve diğer standart ItemsControl türetilmiş denetimleri) sizin için kullanıcı arabirimi sanallaştırması gerçekleştirir. Öğeler görünüme kaydırılmaya yaklaştığında (birkaç sayfa ötede), çerçeve öğeler için kullanıcı arabirimi oluşturur ve bunları önbelleğe alır. Öğelerin yeniden gösterilme olasılığı düşük olduğunda, çerçeve belleği geri alır.
Özel öğeler paneli şablonu sağlarsanız (bkz . ItemsPanel), ItemsWrapGrid veya ItemsStackPanel gibi bir sanallaştırma paneli kullandığınızdan emin olun. VariableSizedWrapGrid, WrapGrid veya StackPanel kullanıyorsanız sanallaştırma alamayabilirsiniz. Ayrıca, aşağıdaki ListView olayları yalnızca ItemsWrapGrid veya ItemsStackPanel kullanılırken tetiklenir: ChoosingGroupHeaderContainer, ChoosingItemContainer ve ContainerContentChanging. Windows Uygulama SDK'sında özel düzenler için, yerleşik öğe panelleri gereksinimlerinizi karşılamıyorsa, modern karşılığı VirtualizingLayout tabanlı bir uygulamadır.
Görünüm penceresi kavramı, ui sanallaştırması için kritik öneme sahiptir çünkü çerçevenin gösterilme olasılığı olan öğeleri oluşturması gerekir. Genel olarak, ItemsControl'un görünüm alanı mantıksal denetimin kapsama alanıdır. Örneğin, ListView'un görünüm penceresi ListView öğesinin genişliği ve yüksekliğidir. Bazı paneller, scrollviewer ve otomatik boyutlandırılmış satır veya sütunlar içeren kılavuz gibi alt öğelere sınırsız alan sağlar. Sanallaştırılmış ItemsControl böyle bir panele yerleştirildiğinde, tüm öğelerini göstermek için yeterli alanı kaplar ve bu da sanallaştırmayı etkisiz hale getirir. ItemsControl üzerinde genişlik ve yükseklik ayarlayarak sanallaştırmayı geri yükleyin.
Öğe başına öğe azaltma
Öğelerinizi işlemek için kullanılan kullanıcı arabirimi öğelerinin sayısını makul bir minimumda tutun.
Bir öğe denetimi ilk kez gösterildiğinde, öğelerle dolu bir görünüm penceresi oluşturmak için gereken tüm öğeler oluşturulur. Ayrıca, öğeler görünüm penceresine yaklaştıkça, çerçeve önbelleğe alınan öğe şablonlarındaki kullanıcı arabirimi öğelerini ilişkili veri nesneleriyle güncelleştirir. Şablonların içindeki işaretlemenin karmaşıklığını en aza indirmek, bellek kullanımında ve kullanıcı arabirimi iş parçacığında harcanan sürede tasarruf sağlayarak özellikle kaydırma ve kaydırma sırasında yanıt verme yeteneğini artırır. Söz konusu şablonlar öğe şablonu (bkz . ItemTemplate) ve ListViewItem veya GridViewItem denetim şablonu (öğe denetim şablonu veya ItemContainerStyle). Öğe sayısında küçük bir azalmanın bile avantajı, görüntülenen öğe sayısıyla çarpılır.
Öğe azaltma örnekleri için bkz. WinUI ve Windows Uygulama SDK'sı için XAML yüklemesini iyileştirme.
ListViewItem ve GridViewItem için varsayılan denetim şablonları bir ListViewItemPresenter öğesi içerir. Bu sunum aracı, odak, seçim ve diğer görsel durumlar için karmaşık görselleri görüntüleyen tek bir optimize edilmiş öğedir. Zaten özel öğe denetimi şablonlarınız varsa (ItemContainerStyle) veya gelecekte bir öğe denetimi şablonunun kopyasını düzenliyorsanız, bu öğe çoğu durumda performans ve özelleştirilebilirlik arasında en uygun dengeyi sağladığından ListViewItemPresenter kullanmanızı öneririz. Sunum cihazının özelliklerini belirleyerek sunum cihazını özelleştirebilirsiniz. Örneğin, bir öğe seçildiğinde varsayılan olarak görüntülenen onay işaretini kaldıran ve seçili öğenin arka plan rengini turuncu olarak değiştiren işaretleme aşağıda verilmiştir.
...
<ListView>
...
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter SelectionCheckMarkVisualEnabled="False" SelectedBackground="Orange"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
<!-- ... -->
SelectionCheckMarkVisualEnabled ve SelectedBackground gibi kendi kendini açıklayan adlara sahip yaklaşık 25 özellik vardır. "Kullanım örneğiniz için sunucu türleri yeterince özelleştirilebilir değilse, bunun yerine ListViewItemExpanded veya GridViewItemExpanded denetim şablonunun bir kopyasını düzenleyebilirsiniz." WinUI uygulamasında, geçerli varsayılan şablonlar için Windows Uygulama SDK'sı paketiyle birlikte gelen dosyaya bakın generic.xaml . Bu şablonları kullanmanın özelleştirmedeki artış için biraz performans takası anlamına geldiğini unutmayın.
ListView ve GridView öğelerini aşamalı olarak güncelleştirme
Veri sanallaştırma kullanıyorsanız, indirilmekte olan öğeler için geçici kullanıcı arabirimi öğelerini işlemek üzere denetimi yapılandırarak ListView ve GridView yanıt hızını yüksek tutabilirsiniz. Daha sonra geçici öğeler, veri yüklendıkça aşamalı olarak gerçek kullanıcı arabirimiyle değiştirilir.
Ayrıca, verileri nereden yüklerseniz yükleyin (yerel diskten, ağdan veya buluttan), kullanıcı bir ListView veya GridView üzerinde o kadar hızlı kaydırma veya gezinme yapabilir ki, her öğeyi tam doğrulukla işlemek, ancak pürüzsüz kaydırma ve gezinmeyi korumak mümkün olmaz. Düzgün bir kaydırma ve geçiş etkisini korumak için, yer tutucuları kullanmanın yanı sıra bir öğeyi birden çok aşamada işlemeyi de seçebilirsiniz.
Bu tekniklerin bir örneği genellikle fotoğraf görüntüleme uygulamalarında görülür: Tüm görüntüler yüklenmemiş ve görüntülenmemiş olsa da, kullanıcı yine de kaydırabilir, kaydırabilir ve koleksiyonla etkileşimde bulunabilir. Alternatif olarak, bir film öğesi için başlığı ilk aşamada, derecelendirmeyi ikinci aşamada ve posterin bir görüntüsünü üçüncü aşamada gösterebilirsiniz. Kullanıcı her öğeyle ilgili en önemli verileri mümkün olan en erken zamanda görür ve bu da aynı anda eylem gerçekleştirebileceği anlamına gelir. Daha sonra, zaman izin verdiğinden daha az önemli bilgiler doldurulur. Bu teknikleri uygulamak için kullanabileceğiniz platform özellikleri aşağıdadır.
Yer tutucular
Geçici yer tutucu görseller özelliği varsayılan olarak açıktır ve ShowsScrollingPlaceholders özelliğiyle denetlenmektedir. Hızlı tarama ve kaydırma sırasında, bu özellik kullanıcıya düzgünlüğü korurken henüz tam olarak görüntülenmemiş daha fazla öğe olduğunu belirten görsel bir ipucu verir. Aşağıdaki tekniklerden birini kullanırsanız, sistemin yer tutucuları işlemesini istemiyorsanız ShowsScrollingPlaceholders değerini false olarak ayarlayabilirsiniz.
x:Phase kullanarak aşamalı veri şablonu güncelleştirmeleri
x:Phase Özniteliği WinUI'de çalışmaya devam eder ve öğe içeriğini aşamalı olarak işlemek için iyi bir yol olmaya devam eder.
Aşamalı veri şablonu güncelleştirmelerini uygulamak için {x:Bind} bağlamalarıyla x:Phase özniteliğini şu şekilde kullanabilirsiniz.
Bağlama kaynağının nasıl göründüğü aşağıdadır (bu, bağlanacağımız veri kaynağıdır).
namespace LotsOfItems { public class ExampleItem { public string Title { get; set; } public string Subtitle { get; set; } public string Description { get; set; } } public class ExampleItemViewModel { private ObservableCollection<ExampleItem> exampleItems = new ObservableCollection<ExampleItem>(); public ObservableCollection<ExampleItem> ExampleItems { get { return this.exampleItems; } } public ExampleItemViewModel() { for (int i = 1; i < 150000; i++) { this.exampleItems.Add(new ExampleItem(){ Title = "Title: " + i.ToString(), Subtitle = "Sub: " + i.ToString(), Description = "Desc: " + i.ToString() }); } } } }İşte
DeferMainPage.xaml'in içerdiği işaretleme. Kılavuz görünümü, MyItem sınıfının Title, Subtitle ve Description özelliklerine bağlı öğeler içeren bir öğe şablonu içerir. x:Phase öğesinin varsayılan olarak 0 olduğunu unutmayın. Burada, öğeler başlangıçta yalnızca başlık görünür hale getirilir. Ardından alt başlık öğesi verilere bağlıdır ve tüm öğeler için görünür hale gelir ve tüm aşamalar işlenene kadar bu şekilde devam eder.<Page x:Class="LotsOfItems.DeferMainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:lotsOfItems="using:LotsOfItems" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <GridView ItemsSource="{x:Bind ViewModel.ExampleItems}"> <GridView.ItemTemplate> <DataTemplate x:DataType="lotsOfItems:ExampleItem"> <StackPanel Height="100" Width="100" Background="OrangeRed"> <TextBlock Text="{x:Bind Title}"/> <TextBlock Text="{x:Bind Subtitle}" x:Phase="1"/> <TextBlock Text="{x:Bind Description}" x:Phase="2"/> </StackPanel> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid> </Page>Uygulamayı şimdi çalıştırıp kılavuz görünümünde hızla kaydırdığınızda, her yeni öğenin ekranda belirdiğinde ilk olarak koyu gri bir dikdörtgen şeklinde görüntülendiğini fark edersiniz (öğeler kayarken yer tutucuların gösterilmesini sağlayan ShowsScrollingPlaceholders özelliğinin varsayılanı true olduğu için), ardından başlık görünür, sonra alt başlık ve ardından açıklama görüntülenir.
ContainerContentChanging kullanarak aşamalı veri şablonu güncelleştirmeleri
ContainerContentChanging olayının genel stratejisi, hemen görünür olması gerekmeyen öğeleri gizlemek için Opacity kullanmaktır. Öğeler geri dönüştürüldiğinde eski değerlerini korurlar, bu nedenle bu değerleri yeni veri öğesinden güncelleştirene kadar bu öğeleri gizlemek istiyoruz. Hangi öğelerin güncelleştirileceğini ve gösterileceğini belirlemek için olay bağımsız değişkenlerinde Phase özelliğini kullanırız. Ek aşama gerektiğinde, bir geri çağrı kaydederiz.
x:Phase ile aynı bağlama kaynağını kullanacağız.
İşte
MainPage.xaml'in içerdiği işaretleme. Kılavuz görünümü, ContainerContentChanging olayı için bir işleyici bildirir ve MyItem sınıfının Title, Subtitle ve Description özelliklerini görüntülemek için kullanılan öğeleri içeren bir öğe şablonu içerir. ContainerContentChanging kullanmanın en yüksek performans avantajlarını elde etmek için, işaretlemede bağlamaları kullanmaz ve bunun yerine değerleri program aracılığıyla atarız. Buradaki istisna, başlığı görüntüleyen ve 0. aşamada olduğunu düşündüğümüz öğedir.<Page x:Class="LotsOfItems.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:lotsOfItems="using:LotsOfItems" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <GridView ItemsSource="{x:Bind ViewModel.ExampleItems}" ContainerContentChanging="GridView_ContainerContentChanging"> <GridView.ItemTemplate> <DataTemplate x:DataType="lotsOfItems:ExampleItem"> <StackPanel Height="100" Width="100" Background="OrangeRed"> <TextBlock Text="{x:Bind Title}"/> <TextBlock Opacity="0"/> <TextBlock Opacity="0"/> </StackPanel> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid> </Page>Son olarak ContainerContentChanging olay işleyicisinin uygulaması aşağıdadır. Bu kod, işaretleme sayfamızı temsil eden sınıftan bağlama kaynak sınıfını kullanıma açmak için MainPage'eExampleItemViewModel türünde bir özelliği nasıl ekleyebileceğimizi de gösterir. Eğer veri şablonunuzda {Binding} bağlaması yoksa, olay bağımsız değişkenlerini işleyicinin ilk aşamasında işlenmiş olarak işaretleyin ve öğeye veri bağlamı ayarlamasına gerek olmadığını belirtin.
namespace LotsOfItems { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); this.ViewModel = new ExampleItemViewModel(); } public ExampleItemViewModel ViewModel { get; set; } // Display each item incrementally to improve performance. private void GridView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { if (args.Phase != 0) { throw new System.Exception("We should be in phase 0, but we are not."); } // It's phase 0, so this item's title will already be bound and displayed. args.RegisterUpdateCallback(this.ShowSubtitle); args.Handled = true; } private void ShowSubtitle(ListViewBase sender, ContainerContentChangingEventArgs args) { if (args.Phase != 1) { throw new System.Exception("We should be in phase 1, but we are not."); } // It's phase 1, so show this item's subtitle. var templateRoot = args.ItemContainer.ContentTemplateRoot as StackPanel; var textBlock = templateRoot.Children[1] as TextBlock; textBlock.Text = (args.Item as ExampleItem).Subtitle; textBlock.Opacity = 1; args.RegisterUpdateCallback(this.ShowDescription); } private void ShowDescription(ListViewBase sender, ContainerContentChangingEventArgs args) { if (args.Phase != 2) { throw new System.Exception("We should be in phase 2, but we are not."); } // It's phase 2, so show this item's description. var templateRoot = args.ItemContainer.ContentTemplateRoot as StackPanel; var textBlock = templateRoot.Children[2] as TextBlock; textBlock.Text = (args.Item as ExampleItem).Description; textBlock.Opacity = 1; } } }Uygulamayı şimdi çalıştırır ve kılavuz görünümünde hızla kaydırır veya pan yaparsanız x:Phase ile aynı davranışı görürsünüz.
Heterojen koleksiyonlarla konteyner geri dönüşümü
Bazı uygulamalarda, bir koleksiyondaki farklı öğe türleri için farklı kullanıcı arabirimine sahip olmanız gerekir. Sanallaştırıcı panellerin öğeleri görüntülemek için kullanılan görsel öğeleri yeniden kullanması veya geri dönüştürmesinin mümkün olmadığı bir durum yaratabilir. Kaydırma sırasında bir öğenin görsel öğelerini yeniden oluşturma işlemi, sanallaştırma tarafından sağlanan performans kazançlarının çoğunu geri alır. Ancak, biraz planlama yapmak, panellerin sanallaştırılarak öğelerin yeniden kullanılmasına olanak tanıyabilir. Geliştiricilerin senaryolarına bağlı olarak birkaç seçeneği vardır: SelectItemContainer olayı veya bir öğe şablonu seçicisi. ChoosingItemContainer yaklaşımı daha iyi performansa sahiptir.
ChoosingItemContainer olayı
ChoosingItemContainer, başlangıç veya geri dönüşüm sırasında yeni bir öğe gerektiğinde ListView veya GridView'a bir öğe (ListViewItem veya GridViewItem) sağlamanıza olanak tanıyan bir olaydır. Aşağıdaki örnekte gösterildiği gibi, kapsayıcının görüntüleneceği veri öğesinin türüne göre bir kapsayıcı oluşturabilirsiniz. ChoosingItemContainer , farklı öğeler için farklı veri şablonlarını kullanmanın daha yüksek performanslı bir yoludur. Kapsayıcı önbelleğe alma, ChoosingItemContainer kullanılarak gerçekleştirilebilir. Örneğin, bir şablonun diğerlerinden daha sık büyüklük sırasına sahip olduğu beş farklı şablonunuz varsa , ChoosingItemContainer yalnızca gerekli oranlarda öğe oluşturmakla kalmaz, aynı zamanda uygun sayıda öğeyi önbelleğe alıp geri dönüşüm için kullanılabilir durumda tutmanızı sağlar. ChoosingGroupHeaderContainer , grup üst bilgileri için aynı işlevselliği sağlar.
// Example shows how to use ChoosingItemContainer to return the correct
// DataTemplate when one is available. This example shows how to return different
// data templates based on the type of FileItem. Available ListViewItems are kept
// in two separate lists based on the type of DataTemplate needed.
private void ListView_ChoosingItemContainer
(ListViewBase sender, ChoosingItemContainerEventArgs args)
{
// Determines type of FileItem from the item passed in.
bool special = args.Item is DifferentFileItem;
// Uses the Tag property to keep track of whether a particular ListViewItem's
// datatemplate should be a simple or a special one.
string tag = special ? "specialFiles" : "simpleFiles";
// Based on the type of datatemplate needed return the correct list of
// ListViewItems, this could have also been handled with a hash table. These
// two lists are being used to keep track of ItemContainers that can be reused.
List<UIElement> relevantStorage = special ? specialFileItemTrees : simpleFileItemTrees;
// args.ItemContainer is used to indicate whether the ListView is proposing an
// ItemContainer (ListViewItem) to use. If args.ItemContainer is not null, then
// there was a recycled ItemContainer available to be reused.
if (args.ItemContainer != null)
{
// The Tag is being used to determine whether this is a special file or
// a simple file.
if (args.ItemContainer.Tag.Equals(tag))
{
// Great: the system suggested a container that is actually going to
// work well.
}
else
{
// The ItemContainer's datatemplate does not match the needed
// datatemplate.
args.ItemContainer = null;
}
}
if (args.ItemContainer == null)
{
// See if we can fetch from the correct list.
if (relevantStorage.Count > 0)
{
args.ItemContainer = relevantStorage[0] as SelectorItem;
}
else
{
// There aren't any recycled ItemContainers available, so a new one
// needs to be created.
ListViewItem item = new ListViewItem();
item.ContentTemplate = this.Resources[tag] as DataTemplate;
item.Tag = tag;
args.ItemContainer = item;
}
}
}
Öğe şablonu seçicisi
Öğe şablonu seçicisi (DataTemplateSelector), bir uygulamanın çalışma zamanında görüntülenecek veri öğesinin türüne göre farklı bir öğe şablonu döndürmesine olanak tanır. Bu, geliştirmeyi daha üretken hale getirir, ancak her öğe şablonu her veri öğesi için yeniden kullanılamayacağından kullanıcı arabirimi sanallaştırmayı daha zor hale getirir.
Bir öğeyi (ListViewItem veya GridViewItem) geri dönüştürdüğünüzde, çerçevenin geri dönüşüm kuyruğunda kullanılabilen öğelerin geçerli veri öğesi tarafından istenen öğe şablonuyla eşleşecek bir öğe şablonuna sahip olup olmadığına karar vermesi gerekir. Geri dönüşüm kuyruğunda uygun öğe şablonuna sahip öğe yoksa yeni bir öğe oluşturulur ve bunun için uygun öğe şablonunun örneği oluşturulur. Öte yandan, geri dönüşüm kuyruğu uygun öğe şablonuna sahip bir öğe içeriyorsa, bu öğe geri dönüşüm kuyruğundan kaldırılır ve geçerli veri öğesi için kullanılır. Öğe şablonu seçicisi, yalnızca az sayıda öğe şablonunun kullanıldığı ve farklı öğe şablonları kullanan öğelerin koleksiyonu boyunca düz bir dağıtım olduğu durumlarda çalışır. Farklı öğe şablonları kullanan öğelerin eşit olmayan bir dağıtımı olduğunda, kaydırma sırasında büyük olasılıkla yeni öğe şablonlarının oluşturulması gerekir ve bu durum sanallaştırma tarafından sağlanan kazançların çoğunu azaltır. Ayrıca, bir öğe şablonu seçici, belirli bir kapsayıcının geçerli veri öğesi için yeniden kullanılıp kullanılamayacağını değerlendirirken yalnızca beş olası adayı dikkate alır. Bu nedenle, WinUI uygulamanızda bir öğe şablonu seçicisi kullanmadan önce verilerinizin bir öğe şablonu seçici ile kullanıma uygun olup olmadığını dikkatlice düşünmelisiniz. Koleksiyonunuz çoğunlukla homojense, seçici çoğu zaman veya her zaman aynı türü döndürür. Homojenliğin nadir istisnaları için ödediğiniz bedelin farkında olun ve ChoosingItemContainer veya iki öğe kontrolü kullanmanın tercih edilip edilmediğini göz önünde bulundurun.
Windows developer