当用户使用 WrapPanel 作为 PanelTemplate 滚动内容时,是否可以加载 Image 类型的 ListboxItems?

发布于 2024-12-27 15:12:22 字数 2461 浏览 5 评论 0 原文

我正在开发一个适用于 Windows Phone 7 的应用程序,该应用程序使用从 ObservableCollection 检索的对象列表填充 WrapPanel

<ListBox ItemsSource="{Binding Photo}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding File}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <toolkit:WrapPanel ItemHeight="150" ItemWidth="150" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

它正在按其应有的方式工作(即加载所有图像),但自 WrapPanel : Panel 以来我遇到了一些性能问题。因此它不会虚拟化任何数据,而是加载 ListBox 的所有 Image 对象,甚至是用户看不到的对象。

ObservableCollection.Count <= 30 时,这种方法是可以的,但随着 Collection 变得越来越大,事情开始变得缓慢。

由于用户最多可以拥有 1000 张图像,因此这种方式根本行不通。即使我绑定缩略图来显示图像对象。

我尝试使用 David Anson 的 LowProfileImageLoader 用于在 UI 线程之外创建图像。并在用户滚动 ListBox 时绑定图像。但它不起作用,因为它需要 UriSource 并且我实际上将 BitmapImage 绑定到 Image.Source,因为图像是正在从 IsolatedStorage 加载。

public class Photo : INotifyPropertyChanged, INotifyPropertyChanging
{
    ...
    ...

    public BitmapImage File
    {
        get
        {
            // Thumbnail
            string filePath = Path.Combine("Images", FileName);

            byte[] data;

            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream isfs = isf.OpenFile(filePath, FileMode.Open, FileAccess.Read))
                {
                    data = new byte[isfs.Length];

                    isfs.Read(data, 0, data.Length);
                    isfs.Close();
                }
            }

            MemoryStream ms = new MemoryStream(data);
            BitmapImage bi = new BitmapImage();

            bi.SetSource(ms);

            return bi;
        }
    }
}

任何人都可以帮助我完成使内容(照片)按照用户看到的方式加载的任务吗?有没有诸如VirtualizingWrapPanelWrapPanel:VirtualizingPanel之类的东西?

谢谢。如果需要任何代码片段,请随时询问。

I'm developing an app for Windows Phone 7 that populates a WrapPanel with a list of objects retrieved from an ObservableCollection<Photo>.

<ListBox ItemsSource="{Binding Photo}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding File}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <toolkit:WrapPanel ItemHeight="150" ItemWidth="150" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

It's working how it's supposed to work (in the means that it's loading all the images), but I'm having some performance issues since WrapPanel : Panel. So it doesn't virtualize any data, loading all the Image objects of the ListBox, even the ones that the user can't see.

This approach is OK when ObservableCollection<Photo>.Count <= 30 but as the Collection gets bigger and bigger things start to get slow.

Since the user can have up to 1000 images, it's simply not going to work this way. Even though I'm binding Thumbnails to display the Image object.

I've tried to use David Anson's LowProfileImageLoader to create Images off the UI thread. And to bind the Images as the user scrolls the ListBox. But it doesn't work since it's expecting an UriSource and I'm actually binding a BitmapImage to the Image.Source, because the images are beeing loaded from IsolatedStorage.

public class Photo : INotifyPropertyChanged, INotifyPropertyChanging
{
    ...
    ...

    public BitmapImage File
    {
        get
        {
            // Thumbnail
            string filePath = Path.Combine("Images", FileName);

            byte[] data;

            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream isfs = isf.OpenFile(filePath, FileMode.Open, FileAccess.Read))
                {
                    data = new byte[isfs.Length];

                    isfs.Read(data, 0, data.Length);
                    isfs.Close();
                }
            }

            MemoryStream ms = new MemoryStream(data);
            BitmapImage bi = new BitmapImage();

            bi.SetSource(ms);

            return bi;
        }
    }
}

Can anyone help me in this task of making the content (photos) load as the user sees it? Is there anything such as a VirtualizingWrapPanel or WrapPanel : VirtualizingPanel?

Thanks. If any code snippet is needed feel free to ask.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美人迟暮 2025-01-03 15:12:22

当用户滚动时将图像从存储加载到内存将使您的 UI 变得紧张,尤其是当用户尝试快速滚动或查看更多元素时。
但是,如果内存中有所有图像,然后希望在滚动时将图像绑定到列表框,则可以使用 VirtualizingStackPanel。环绕面板需要知道图像的大小才能正确显示。如果您知道图像的大小并且它们都相同,则可以使用解决方法。

您可以自定义VirtualizingStackPanel并将图像按行放置,就像在包装面板中那样,或者您喜欢的任何其他方式。

希望有帮助。

虽然,
我不确定当你有 1000 张沉重的图像时这是否能解决问题。但如果您还没有这样做的话,值得一试。

编辑: 此文章可能会有所帮助。

Loading the images to memory from the storage when the user scrolls will make your UI jittery especially when the user tries to scroll or see more elements very quickly.
But, if you have all the images in memory and then would like to bind the images to the listbox on scrolling, you could use the VirtualizingStackPanel. A wrap panel would need to know the size of the images to display correctly. A workaround is possible if you know the size of the images and if they're all the same.

You could customize the VirtualizingStackPanel and position the images in rows like the way they would in a wrappanel, or any other way you like.

Hope that helps.

Although,
I am not sure if this will solve the problem when you have 1000 heavy images. But it is worth a try, if you haven't done so.

EDIT: This article might help.

并安 2025-01-03 15:12:22

尝试从虚拟列表框创建环绕面板。
这里是一个如何操作的链接。它工作得很好,但它有一个问题...它将对整行而不是一个项目产生倾斜效果...我目前正在调查这个问题。

Try creating a wrap panel from a virtualized listbox.
Here is a link how to do it. it works pretty good, but it has 1 problem... it will have a tilt effect on a whole line instead of an item... I'm currently investigating that problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文