0

I am making this app for windows phone 7, what I do is retrieve all the images from camera roll, saved pictures and other folder and display them in the listbox inside a wrap panel so they are displayed side by side....the thumbnail of the images is actually displayed hear..... but as the number of images are increasing UI gets very slow and scrolling takes time...

I read many post and other question I think data virtualization or lazy loading is what I need but I am not understanding how can I use it, I saw the post from shawn oster and peter torr.....

I use a backgroundworker to load the images... here's how...

 void backroungWorker1_DoWork(object sender, DoWorkEventArgs e)
    {

        Dispatcher.BeginInvoke(() =>
        {
            foreach (string fileName in fileStorage.GetFileNames("images//*.*"))
            {
                if (fileName == null)
                    break;
                string filepath = System.IO.Path.Combine("images", fileName);
                try
                {
                    using (IsolatedStorageFileStream imageStream = fileStorage.OpenFile(filepath, FileMode.Open))
                    {
                        var imageSource = PictureDecoder.DecodeJpeg(imageStream);
                        BitmapImage bitmapImage = new BitmapImage();
                        bitmapImage.SetSource(imageStream);
                        var item = new ImageToName { bmp = bitmapImage, FileName = fileName };
                        vltBitmapImage.Add(item);
                        imageStream.Dispose();
                        imageStream.Close();
                    }
                }
                catch
                {
                    Exception x = new Exception();
                }
            }
            if (vltBitmapImage.Count() != 0)
            {
                lone.Visibility = Visibility.Collapsed;
                this.vaultbox.ItemsSource = vltBitmapImage;
            }
            else
                lone.Visibility = Visibility.Visible;
        });
    }

any help is greatly appreciated..... sorry for being a noob...

goldsmit409
  • 478
  • 4
  • 26

2 Answers2

0

Try this sample from code project, it explain how it work and comes with a full sample project

See: Loading Data when the User scrolls to the end of the list

  • Please add a better explanation to this answer; see http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers – praseodym Jan 10 '13 at 21:53
0

If you want to add a Lazy load to a listbox you must setup a listner for your list box and change the way you load data into your data model, so first lest set up at the XAML code for a listbox:

In your page resource add this style, and note the loaded event its include ("ScrollViewer_Loaded"):

...
  <phone:PhoneApplicationPage.Resources>
    <Style x:Key="BusinessListBoxStyle"
           TargetType="ListBox">
        <Setter Property="Background"
                Value="Transparent" />
        <Setter Property="Foreground"
                Value="{StaticResource PhoneForegroundBrush}" />
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
                Value="Disabled" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility"
                Value="Auto" />
        <Setter Property="BorderThickness"
                Value="0" />
        <Setter Property="BorderBrush"
                Value="Transparent" />
        <Setter Property="Padding"
                Value="0" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBox">
                    <ScrollViewer x:Name="scrollViewer"
                                  BorderBrush="{TemplateBinding BorderBrush}"
                                  BorderThickness="{TemplateBinding BorderThickness}"
                                  Background="{TemplateBinding Background}"
                                  Foreground="{TemplateBinding Foreground}"
                                  Padding="{TemplateBinding Padding}"
                                  Loaded="ScrollViewer_Loaded">
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</phone:PhoneApplicationPage.Resources>

...

The add a reference to your style for the listbox, and bind your itemsSource to a list of items from your viewModel.

...
        <ListBox x:Name="myList"
                 ItemsSource="{Binding myDataSource}"
                 Style="{StaticResource BusinessListBoxStyle}">

...

Next you have to set some code that loads data into the datamodel, when you reach the end of the list element in the list (the datamodel start loading more data into the mode, adds more items) Lazyloading!!

The way i normaly do this is by listing to the vertical offset of the listbox's scrollbar, and if its is about 1/4 from the edge i starts loading more items into the datamodel. In the ScrollViewer loaded handler i set up at VertialOffset listener, by using the DependencyProperty, see code below:

        public static readonly DependencyProperty ListVerticalOffsetProperty =
        DependencyProperty.Register(
                                    "ListVerticalOffset",
                                    typeof(double),
                                    typeof(MyPage),
                                    new PropertyMetadata(new PropertyChangedCallback(OnListVerticalOffsetChanged))
                                    );

    private ScrollViewer _listScrollViewer;

    private void ScrollViewer_Loaded(object sender, RoutedEventArgs e)
    {
        _listScrollViewer = sender as ScrollViewer;

        Binding binding = new Binding();
        binding.Source = _listScrollViewer;
        binding.Path = new PropertyPath("VerticalOffset");
        binding.Mode = BindingMode.OneWay;
        this.SetBinding(ListVerticalOffsetProperty, binding);
    }

    public double ListVerticalOffset
    {
        get { return (double)this.GetValue(ListVerticalOffsetProperty); }
        set { this.SetValue(ListVerticalOffsetProperty, value); }
    }

    private double _lastFetch;

    private static void OnListVerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        MyPage page = obj as MyPage;
        ScrollViewer viewer = page._listScrollViewer;

        if (viewer != null)
        {
            if (page._lastFetch < viewer.ScrollableHeight)
            {
                // Trigger within 1/4 the viewport.
                if (viewer.VerticalOffset >= (viewer.ScrollableHeight - (viewer.ViewportHeight / 4)))
                {
                    page._lastFetch = viewer.ScrollableHeight;
                    MyViewModel _tmpviewmodel = page.DataContext as MyViewModel;

                    if ((_tmpviewmodel != null) && (_tmpviewmodel.HasMoreItems))
                        _tmpviewmodel.GetMoreItems();
                }
            }
        }
    }

Note here i make use of a MyViewModel, that holds all the items the listbox i binded to, and has methods for load items from a database, the isolatedstore, the web or what ever your needs are.

You just have to find your way of only load a part of your data into the viewmodel. I your case i will first load a list of all the files you need to load (that is just to retreive the list from GetFileNames in the IsoLatedStore). Then mayby only loads 20 pics at the time!