WinRT ListView UI虚拟化和DataTemplateSelector,具有大量模板(10-15)
本文关键字:10-15 UI ListView 虚拟化 DataTemplateSelector WinRT | 更新日期: 2023-09-27 17:58:58
我需要显示具有不同项目的ListView(总共10-15个项目类型)。为此,我使用DataTemplateSelector。但这会导致ListView在滚动过程中出现奇怪的行为:在某个时刻,它会跳到列表视图的顶部。我为UWP找到了这篇文章:https://msdn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-gridview-and-listview.它说ItemTemplateSelector只支持5个DataTemplates
此外,项目模板选择器在评估特定容器是否可以用于当前数据项目时,只考虑五个可能的候选者。
我认为这就是原因。我试图减少DataTemplateSelector返回的DataTemplates的数量,它解决了这个问题:滚动按预期工作。但是,如何在不减少数据模板数量的情况下解决此问题?我知道我可以禁用虚拟化,但如果可能的话,我希望继续启用它。
对于UWP,可以选择使用ChoosingItemContainer事件,但它不适用于WinRT。
是否可以在不禁用WinRT中的UI虚拟化的情况下解决此问题?
这就是我最终在项目中所做的(我有一个无限滚动的列表视图)。基本上,我自己做了一部分虚拟化。
我完全删除了DataTemplateSelector
。相反,我对所有项目使用一个模板:
<ListView
...
>
<ListView.ItemTemplate>
<DataTemplate>
<messages:MyCustomContainer />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
其中MyCustomContainer
是一个简单的UserControl:
<UserControl
x:Class="MyCustomContainer"
...
DataContextChanged="OnDataContextChanged"
>
<Grid x:Name="Container"/>
</UserControl>
我在MyCustomContainer
:的代码背后实例化并选择合适的嵌套模板
void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
var context = DataContext as MyModelThatHelpsDecideOnAppropriateVisualTemplate;
if (context == null) {
// this means, item has been removed from the list and cached (we call this 'virtualization')
Container.Children.Remove(CurrentTemplate);
ReleaseTemplate(CurrentTemplate); // clear and cache our concrete template
CurrentTemplate = null;
} else {
// this means, we need to get a concrete template
// ... some logic to decide on the proper visual template type
Type templateType = GetTemplateTypeForData(context);
// ... some logic to get visual template from cache
CurrentTemplate = GetTemplateFromCache(templateType);
Container.Children.Add(CurrentTemplate);
}
}
从好的方面来看,这很好(对我来说很好,我有大约十几个项目模板)。
另一方面,通过这种方式,UI框架只虚拟化MyCustomContainer
列表项,并且您必须自己缓存具体的视觉效果。在我的示例中,您必须将10-15个模板的实例存储在某个缓存中,并实现GetTemplateTypeForData()
、GetTemplateFromCache()
和ReleaseTemplate()
。。。但这应该非常简单,我花了大约100行代码。