Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy-loading visible items in a Listview

I have a listview which uses the following code:

<ListView x:Name="Display" ItemsSource="{Binding}" Background="#373737" Margin="0,0,350,0" BorderThickness="0" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" Width="767" Height="88">
                    <Border Height="64" Width="64" Margin="12,12,0,12">
                        <Image Source="{Binding Path=album.albumart}" Stretch="UniformToFill"/>
                    </Border>
                    <StackPanel Orientation="Vertical" VerticalAlignment="Top" Margin="0,10,0,0">
                        <TextBlock Text="{Binding Path=name}" 
                   Margin="10,0,0,0" Width="300" Height="40" 
                   TextTrimming="WordEllipsis" TextWrapping="Wrap" FontSize="16" HorizontalAlignment="Left"/>
                        <TextBlock Text="{Binding Path=album.name}" 
                   Margin="10,-15,0,0" Width="300" Height="20" 
                   TextTrimming="WordEllipsis" HorizontalAlignment="Left" 
                   FontSize="14" Opacity="0.49"/>
                        <TextBlock Text="{Binding Path=artistname}" 
                   Margin="10,2,0,0" Width="300"
                   TextTrimming="WordEllipsis" HorizontalAlignment="Left" 
                   FontSize="12" Opacity="0.49"/>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

And I have about 400 objects with images (this takes quite a bit of memory)

Which are then displayed in each listviewitem.

Is there any way for the listview to tell items to load their image from a cache I have based on which objects are visible in the listview instead of having all the images loaded all the time, which, as previously said takes quite a bit of memory.

Hope you guys understand what I'm on about, thank you.

like image 855
Tokfrans Avatar asked Jan 23 '14 20:01

Tokfrans


1 Answers

I tried this solution with my pictures folder containing more than 3500 pictures in high resolution. Memory usage peaked at 120MB with furious scrolling which seemed to trigger garbage collection and reduced memory to about 50MB.

 <ListBox ItemsSource="{Binding Images}" VirtualizingPanel.IsVirtualizing="True">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Image Height="64" Width="64">
                    <Image.Source>
                        <BitmapImage
                            DecodePixelHeight="64"
                            DecodePixelWidth="64"
                            UriSource="{Binding Path=., Mode=OneWay,UpdateSourceTrigger=Explicit}" 
                            CreateOptions="DelayCreation" 
                            CacheOption="None"  />
                    </Image.Source>
                </Image>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

ViewModel:

public class ViewModel : INotifyPropertyChanged
    {
        public ICollectionView Images { get; private set; }
        public ViewModel()
        {
        }
        public void LoadImages()
        {
            var folder = @"C:\Users\lrved_000\Pictures";
            var photos = System.IO.Directory.EnumerateFiles(folder, "*.jpg",SearchOption.AllDirectories);

            Images = CollectionViewSource.GetDefaultView(photos);
            RaisePropertyChanged("Images");
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    }
like image 67
Lorentz Vedeler Avatar answered Nov 03 '22 05:11

Lorentz Vedeler