Question

I am working on windows phone application which having ListBox with Image & text block. Here image is located in IsolatedStorage of application.To display Image in ListBlock I'm converting into stream. After this I am using DataContractSerializer to serialize & store in Isolatedstorage.

Code in Page1:

public BookDataList listobj = new BookDataList();

public class BookDataList : List<BookData>//for storing BookData class items with type of list
{
}  

    [DataContract]
public class BookData
{
    [DataMember]
    public BitmapImage ImageBinary
    {
        get { return m_ImageBinary; }
        set { m_ImageBinary = value; }
    }

    [DataMember]
    public BitmapImage m_ImageBinary;

    public BookData(string strImageName)
    {
        //*** Image Binary ***'
        BitmapImage image = new BitmapImage();
        IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
        string isoFilename = strImageName;
        Stream stream = isoStore.OpenFile(isoFilename, System.IO.FileMode.Open);
        image.SetSource(stream);
        this.ImageBinary = image;
        stream.Close();
    }

    [DataMember]
    public string BookName { get; set; }

    [DataMember]
    public string BookPath { get; set; }

    [DataMember]
    public string FolderPath { get; set; }
}

Here I am adding items to list datatype :

            listobj.Add(new BookData(CoverImageForLib) { BookName = MyTitle.Value,  
BookPath = item.Path, FolderPath = split[1] });

Here I am storing to file in Isolated storage :

  if (Settings1.FileExists("MyStoreItems"))
  {
      Settings1.DeleteFile("MyStoreItems");
  }
  using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MyStoreItems", FileMode.Create))
  {
      DataContractSerializer serializer = new DataContractSerializer(typeof(BookDataList));
      serializer.WriteObject(fileStream, listobj);
  }
  NavigationService.Navigate(new Uri("/Library.xaml", UriKind.Relative));

Here I am just storing the values. I will Deserialize the values in my /Library.xaml from my file MyStoreItems

Edit:

I got something relevant from here

  1. Your "BookData" class does not have a public parameterless constructor. This will cause an error when attempting to reload the data.

  2. BitmapImage class is not serializable.

In order to work around these two problems you would need to write custom serialization code, which you can do by adding the interface: "IXmlSerializable" to your class and implementing the GetSchema, ReadXml, and WriteXml methods.

I am getting System.Reflection.TargetInvocationException exception while serializing listobj.

If the code is confusing, please ask me questions so I can clarify.

Edit 1:

[DataContract]
public class BookData
{
    [DataMember]
    public string BookName { get; set; }
    [DataMember]
    public string Creator { get; set; }
    [DataMember]
    public string BookPath { get; set; }
    [DataMember]
    public string BookCoverPath { get; set; }
    [DataMember]
    public string FolderPath { get; set; }
    [DataMember]
    public BitmapImage Image { get; set; }
}

public class BookDataList : List<BookData>//for storing BookData class items with type of list
{

}  

I serialized & stored BookCoverPath as string. But whenever I am trying to deserialize it is giving exception. I am not familiar with DataContractSerializer. Can you look into it that what I did wrong.

 // Here I getting data from file in Isolated storage
    if (Settings1.FileExists("MyStoreItems"))
        {
            using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MyStoreItems", FileMode.Open))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(BookData));
                listobj1 = (BookDataList)serializer.ReadObject(fileStream);
            }
        }
    foreach (var item in listobj1)
    {
        string imagePath = item.BookCoverPath;
        item.Image = BookData(imagePath);
    }
    ListBox.ItemsSource = listobj1;//binding isolated storage list data

    public BitmapImage BookData(string imagePath)
    {
        //*** Image Binary ***'
        BitmapImage image = new BitmapImage();
        IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
        string isoFilename = imagePath;
        Stream stream = isoStore.OpenFile(isoFilename, System.IO.FileMode.Open);
        image.SetSource(stream);
        stream.Close();

        return image;
    }
Was it helpful?

Solution

The BookData class has implemented logic to load the BitmapImage. If you want to persist / serialize a class in XML, strip this code away to get a simple DTO. This won't give you any trouble to serialize and save. only serialize the imageName. You won't need a custom XML serializer at all.

To get your Bitmap, load the bitmap after you deserialize the xml. you can eighter use the imageName to resolve bitmap within your view by simply load the image by url. Or create a Bitmap Property of your BookData (But marked as [IgnoreDataMember]). After deserialize the element, load the Bitmap from your isolatedStorage in a second step and set the Bitmap on your BookData.

[DataContract]
public class BookData
{
    [DataMember]
    public string BookCoverPath { get; set; }

    [IgnoreDataMember]
    public BitmapImage Image { get; set; }
}


public BookDataList LoadList()
{
  var booklist = loadAndDeserializeFromXML();
  return booklist == null 
    ? null 
    : this.WithBitmaps(booklist );
}

private BookDataList WithBitmaps(BookDataList bookData)
{
  bookData.BookData.ForEach(b =>
  {
    b.Image= loadPicture(b.BookCoverPath );
  });               
  return bookData;
}

Due to abstraction and testing i would recomend you, to implemented loadAndDeserializeFromXML() and loadPicture(string path) in a repository class. Not the ViewModel/CodeBehind itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top