Windows phone 7 windows phone虚拟化画布可实现更高效、更灵活的列表框,这是一种正确的方法吗?
背景: 我正在开发这个应用程序。其中一页是新闻提要。新闻中的数据是动态的:它可能包含多个文本块、许多图像,并根据内容计算每个新闻项的布局 由于无法(我不知道如何)使其与ListBox/DataTemplate/Binding一起工作,因此我采用了较低级别的方法,并尝试实现虚拟化画布: 想法很简单: 每个包含的项实现: 可虚拟化的公共接口 { void ChangeState(VirtualizableState newState) -面板应放入ScrollViewer并初始化:Windows phone 7 windows phone虚拟化画布可实现更高效、更灵活的列表框,这是一种正确的方法吗?,windows-phone-7,windows-phone-8,windows-phone,Windows Phone 7,Windows Phone 8,Windows Phone,背景: 我正在开发这个应用程序。其中一页是新闻提要。新闻中的数据是动态的:它可能包含多个文本块、许多图像,并根据内容计算每个新闻项的布局 由于无法(我不知道如何)使其与ListBox/DataTemplate/Binding一起工作,因此我采用了较低级别的方法,并尝试实现虚拟化画布: 想法很简单: 每个包含的项实现: 可虚拟化的公共接口 { void ChangeState(VirtualizableState newState) -面板应放入ScrollViewer并初始化: public
public void InitializeWithScrollViewer(ScrollViewer _scrollViewer)
{
_listScrollViewer = _scrollViewer;
EnsureBoundToScrollViewer();
}
protected void EnsureBoundToScrollViewer()
{
Binding binding = new Binding();
binding.Source = _listScrollViewer;
binding.Path = new PropertyPath("VerticalOffset");
binding.Mode = BindingMode.OneWay;
this.SetBinding(ListVerticalOffsetProperty, binding);
}
面板实现了AddItems方法:
公共无效附加项(IEnumerable\u itemstobedded)
{
double topMargin = 0;
foreach (var itemToBeAdded in _itemsToBeAdded)
{
itemToBeAdded.View.Margin = new Thickness(0, itemToBeAdded.Margin.Top + topMargin, 0, 0);
_virtualizableItems.Add(itemToBeAdded);
topMargin += itemHeightIncludingMargin;
}
Height = topMargin;
}
然后根据滚动位置的变化加载和卸载项目:
私有void LoadItemsInSegment(段段,虚拟化状态desiredState)
{
对于(inti=segment.LowerBound;i我认为您的虚拟化面板不会虚拟化任何东西 在上下文中,虚拟化的工作方式如下。您需要显示10000个数据项。屏幕仅适合15个UI元素。系统提供的VirtualzingStackPanel创建~17个UI元素,在用户滚动列表时重用这些元素。当UI元素离开屏幕时,面板“释放”UI元素(如果需要,可以进行干预,请参见
ClearContainerForItemOverride
方法)。并为以后的重用做好准备(同样,如果需要,可以进行干预,请参见PrepareContainerForItemOverride
)。如果需要更多元素(例如,因为数据项越来越小),则会创建新的UI元素
关键是你有10000个虚拟物品,而实际物品只有17个,因此虚拟化
然而,在你的代码中,我明白了
public interface IVirtualizable
{
FrameworkElement View { get; }
}
这意味着您的数据项和UI元素之间存在1对1的关系。UI元素非常昂贵,它们拥有GPU纹理和其他系统资源。这就是为什么添加更多元素时会出现性能问题的原因
重新实现VirtualizingStackPanel很难。它的代码是MyVirtualizingPanel类的3-4倍。幸运的是,您不需要这样做,它已经在框架中,而且功能非常广泛。如果您不喜欢列表框,因为它是选中/未选中的内容,请使用普通ItemsControl,将ItemContainer设置为VirtualizingStackPanel.谢谢你有意义的回答。我不完全同意你的观点。事实上,我的虚拟化面板没有回收容器,但虚拟化已经到位。IVirtualizable.View(在我所有的IVirtualizable实现中都是画布)只有当相应的元素处于加载状态时,面板才能访问。因此,接口的实现者可以在卸载时将view=null设置为空,并在加载时重新实例化它。我正在识别问题中描述的问题,实际上我倾向于认为我的方法会起作用。将返回结果。
item.ChangeState(desiredState);
if (!Children.Contains(item.View))
{
Children.Add(item.View);
}
}
}
item.ChangeState(desiredState);
if (!Children.Contains(item.View))
{
Children.Add(item.View);
}
}
}
private void UnloadItemsInSegment(Segment segment)
{
for (int i = segment.LowerBound; i <= segment.UpperBound; i++)
{
var item = _virtualizableItems[i];
Children.Remove(item.View);
item.ChangeState(VirtualizableState.Unloaded);
}
}
public interface IVirtualizable
{
FrameworkElement View { get; }
}