Qui*_*ncy 9 c# windows-runtime windows-8.1 windows-phone-8.1
我正在实现一个可以轻松拥有10,000张小图片的列表.实际用例显示视频的缩略图列表,以便您可以逐帧滚动视频.我在视频中每2/3秒钟将视频的缩略图放入列表中.我需要支持很长的视频(例如1小时视频).
所以虚拟化选项:
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh780657.aspx
我试过"增量数据虚拟化",这对我来说消耗太多内存,因为图像只能通过流来引用,我最终会打开10,000个流.由于内存不足,这会导致Windows Phone应用程序崩溃.
现在我想尝试"随机访问数据虚拟化".我看到如何实现接口IObservableVector<object>, INotifyCollectionChanged(是的<object>b/c <T>不起作用).棘手的部分是如何处理图像和加载图像.加载图像是一种异步方法.
此外,我认为,这个解决方案应该有占位符就像MSFT医生说"这种类型的数据虚拟化的例子经常出现在图片浏览应用程序,而是让用户等待下载所有相册内的照片,应用程序会显示占位符图片当检索到每个图像时,应用程序用实际照片的渲染替换该图像的占位符元素.即使所有图像都没有被下载和显示,用户仍然可以平移并与该集合交互.
查看占位符的MSFT示例 - 使用"ContainerContentChanging"似乎是一条重要的路径.我猜这里有一种方法可以在这个事件中处理图像,并开始加载图像. https://code.msdn.microsoft.com/windowsapps/ListViewSimple-d5fc27dd
将其归结为一个问题 - 在哪里可以处理图像流并为随机访问虚拟化列表开始加载图像? 这是照片应用程序中非常常见的场景,在iOS中非常容易,但似乎没有人在Windows运行时完成它.
您必须调整 VirtualizingCollection 的实现,请查看以下文章http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization。
我使用适用于 Windows Phone 8.1 运行时应用程序的 VirtualizingCollection 改编版编写了一个示例应用程序。
public class ThumbnailItem
{
public Uri ImageUri { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
稍后编写 ThumbnailItem 提供程序。
public class ThumbnailProvider : IItemsProvider<ThumbnailItem>
{
private readonly int _itemsCount;
public ThumbnailProvider(int itemsCount)
{
_itemsCount = itemsCount;
}
public int FetchCount()
{
return _itemsCount;
}
public IList<ThumbnailItem> FetchRange(int startIndex, int count)
{
var items = new List<ThumbnailItem>();
while (count-- > 0)
{
items.Add(new ThumbnailItem()
{
ImageUri = new Uri("ms-appx:///Assets/Square71x71Logo.scale-240.png")
});
}
return items;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在 ViewModel 内部,您必须创建一个 IList 属性并使用 VirtualizingCollection 的实现来设置该值。我建议您使用 AsyncVirtualizingCollection。
Items = new AsyncVirtualizingCollection<ThumbnailItem>(new ThumbnailProvider(1000000), 100);
Run Code Online (Sandbox Code Playgroud)
最后,在视图上,您必须使用 ViewModel 的实例设置 DataContext 对象,并且 ListView 应类似于:
<ListView
ItemsSource="{Binding Items,Mode=OneWay}"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="0 0 20 20">
<Image Source="{Binding ImageUri,Mode=OneTime}"
Width="72" Height="72"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
Run Code Online (Sandbox Code Playgroud)
当然,提供者的逻辑必须根据您的要求进行更改,我编写的代码只是一个示例。
如果对您有帮助,请标记为答案。
最好的问候,丹尼斯
编辑 朋友@Quincy,我发布了一个简单的例子,你可以改编它。也许对于您的应用程序,ThumbnailItem 类将包含指示 IsolateStorageFile 文件名的 Filename 属性。在这种情况下,您必须使用转换器创建 Binding,因此您需要实现 IValueConverter 对象以使用 IsolateStorageFile 创建 BitmapImage 实例。
BitmapImage 图像 = new BitmapImage(); 图像.SetSource(源文件); 返回图像;
关于图像关闭,VirtualizingCollection定义了一个pagesize,默认为100。您的 IsolateStorageFiles 将被用于在 IValueConverter 对象中创建 BitmapImage 一次。稍后,VirtualizingCollection 将删除不使用的旧页面(未显示,请检查 VirtualizingCollection 实现),最后 GC 将关闭并处置 BitmapImage。
移植 VirtualizingCollection 很容易,我记得我只是对 AsyncVirtualizingCollection 类进行了更改。我的解决方案很简单:
将 ThreadPool.QueueUserWorkItem 替换为 ThreadPool.RunAsync。
将 Trace 替换为 Debug(只是调试消息,并不重要)。
使用以下命令替换 SynchronizationContext 方法调用:
(对于 Windows Phone 应用程序)CoreApplication.MainView.CoreWindow.Dispatcher。
(对于 Windows 应用程序)CoreApplication.MainView.Dispatcher。
我希望它对你有帮助。
| 归档时间: |
|
| 查看次数: |
2152 次 |
| 最近记录: |