This is a migrated thread and some comments may be shown as answers.

Reading from local disk

6 Answers 101 Views
TileView
This is a migrated thread and some comments may be shown as answers.
HDC
Top achievements
Rank 1
HDC asked on 31 Jul 2011, 07:46 PM
I am making an OOB application that is to become a picture viewer that will show all images from the local disk.

I can do this using the scripting object and i am capable of showing all the images (limited of course to the types of images that silverlight can visualize)

But the problem is that it is very slow! ( 150 images of average size takes minutes)

If you set the image source in the tiles to a "Path", the tile view control will load the images extremely fast. But when the images have to be loaded from the local drive it is not possible to use a Path (even SL5 will not show images with a local path... at least not in the beta).

So in this case i need to load the images from the drive and then set the source to loaded image:
dynamic fileSystem = AutomationFactory.CreateObject("Scripting.FileSystemObject");
var BinaryStream = AutomationFactory.CreateObject("ADODB.Stream");
BinaryStream.Type = 1;
dynamic files = fileSystem.GetFolder(string.Format(@"{0}", path)).Files;
int counter = 0;
int totalfiles = files.Count;       
foreach (var file in files)
{
    if (file.Type.ToLower().Contains("png") || file.Type.ToLower().Contains("jpeg"))
    {
      BinaryStream.Open();
      BinaryStream.LoadFromFile(file.Path);             
      byte[] ReadBinaryFile = BinaryStream.Read();
      BinaryStream.Close();
       
      BitmapImage bmp = HelperClasses.ImageHelper.LoadImage(ReadBinaryFile);                           
      _photosbeforesort.Add(new Photo() { Id = file.Path, Description = file.Name, Image = bmp, Author=null, CreationDate = DateTime.Parse(file.DateCreated.ToString()) });     
    }           
  }
}

Even though this works, it is extremely slow... because all the images must be loaded in memory.

My question now is... is there a way that i can make the RadTileView load these images "on demand", so that the image is only loaded when it is shown for the first time?







6 Answers, 1 is accepted

Sort by
0
Tina Stancheva
Telerik team
answered on 03 Aug 2011, 01:50 PM
Hello Peter,

Have you tried the virtualization feature of the RadTileView control. You can read more here or examine its implementation and functionality here. Give it a try and let us know if it helps.

Kind regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>

0
HDC
Top achievements
Rank 1
answered on 03 Aug 2011, 02:03 PM
Hi Tina,

Thanks for your reply.

I am already using virtualization, but the problem is that the silverlight image control will not load images that are refering to a local path... You can not set the image Source URI to "c:\images\me.png". Silverlight simply refuses to show anything, i imagine for security reasons. So the problem i am facing is that i need to load the images manually ... i have made a little progress on this, i'm now using an event on the image "Image_Loaded" to load the image from disk:

private void Image_Loaded(object sender, RoutedEventArgs e)
   {
       if ((sender as Image).Tag != null)
       {
           string name = (sender as Image).Tag.ToString();
           (sender as Image).Source = HelperClasses.ImageHelper.LoadImageLocal(name);
       }
   }


But the problem is that, when the user scrolls down with the tiles, the image gets unloaded again and when he scrolls back up all the images need to reload again, making the whole experience ... well ... painful... especially with large images.

It is probably normal that this happens as the tiles probably get destroyed when the user scrolls, so i'm wondering how we can solve this problem?


0
Tina Stancheva
Telerik team
answered on 03 Aug 2011, 02:08 PM
Hi Peter,

So basically what you need is to create all RadTileViewItems as soon as the RadTileView control is loaded and not to recreate them later on? If this is the case, then turning off the virtualization should do the trick.

However, if I am still missing something, can you send us a sample project or code snippets illustrating how you create the TileViewItems and when the Image_Loaded() method is called? This will help us get a clearer view of your scenario.

Best wishes,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>

0
HDC
Top achievements
Rank 1
answered on 03 Aug 2011, 02:38 PM
I can see this is heading towards turning off the virtualization, but it's not a good option because I am expecting large image collections

The tileview is bound to a viewmodel that contains a collection of images:
private ObservableCollection<Photo> Photos = new ObservableCollection<Photo>();

The application contains a treeview resembling the folder structure of the local disk, when a node is clicked all images are loaded from the folder. I have made a datatemplate for the tiles:
<DataTemplate x:Key="PhotoTemplate">
        <telerik:RadFluidContentControl ContentChangeMode="Manual" TransitionDuration="0:0:.5"
        State="{Binding State, Converter={StaticResource tileConverter}}" >
        <telerik:RadFluidContentControl.SmallContent>
          <Image Tag="{Binding Tag}" Source ="{Binding Image}" Stretch="Uniform" Loaded="Image_Loaded"/>
        </telerik:RadFluidContentControl.SmallContent>
      </telerik:RadFluidContentControl>
</DataTemplate>

When virtualization is used on "normal" URI ... does the component reload the images each time there too?





0
HDC
Top achievements
Rank 1
answered on 05 Aug 2011, 05:13 PM
I have finally figured out a solution.

I have made a datatemplate and i using a converter (based on http://www.telerik.com/community/forums/silverlight/tileview/dynamic-tiles.aspx
) to inject an image into the template
<DataTemplate>
    <telerik:RadFluidContentControl ContentChangeMode="Automatic" TransitionDuration="0:0:.5" State="{Binding State, Converter={StaticResource tileConverter}}" >
        <telerik:RadFluidContentControl.Content>
            <ContentPresenter Content="{Binding Converter={StaticResource myConverter}}" />
        </telerik:RadFluidContentControl.Content>
    </telerik:RadFluidContentControl>
</DataTemplate>

The converter looks like this:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
  Image img = new Image();
   
  string localfilename = (value as Photo).Tag.ToString();
  if ((value as Photo).Thumb == null)    
    img.Dispatcher.BeginInvoke(new Action<Image, string, Photo>(LoadImage), img, localfilename, (value as Photo));
 
  return img;
}
 
public void LoadImage(Image me, string localfilename, Photo thephoto)
{
  WriteableBitmap bmp = HelperClasses.ImageHelper.LoadImageLocal(localfilename, 180);
  thephoto.Thumb = bmp;
  me.Source = bmp;
}

For the code of LoadImageLocal i can warmly recommend following reading:

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/12/17/silverlight-s-big-image-problem-and-what-you-can-do-about-it.aspx


It is not simplest of things to do, but it has a performance that far exceeds anything i have been able to get out of it so far. It's quite painfull to load files from the local filesystem in silverlight.

I hope this code may help others trying to do the same thing.

Thanks a lot for putting me on the right track once more Tina!

Best Regards,

Peter

0
Accepted
Tina Stancheva
Telerik team
answered on 08 Aug 2011, 12:44 PM
Hello Peter,

I am truly happy that you found a solution to fit your needs. And I want to thank you for sharing it with the community. I am sure it will be highly appreciated.

Kind regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>

Tags
TileView
Asked by
HDC
Top achievements
Rank 1
Answers by
Tina Stancheva
Telerik team
HDC
Top achievements
Rank 1
Share this question
or