0

I have been using a helper class that saves and retrieves values from isolated storage using key, value pairs. This has worked for individual values that are changed in my application, but I am now attempting to use it for an ObservableCollection in which items will be added and removed during runtime. For some reason, my ObservableCollection is not stored and/or retrieved from IsolatedStorage when the application is closed and reopened. I am not sure what I am doing wrong, because this works for individual values just fine?

Setting.cs

public class Setting<T>
{
    string name;
    T value;
    T defaultValue;
    bool hasValue;

    public Setting(string name, T defaultValue)
    {
        this.name = name;
        this.defaultValue = defaultValue;
    }

    public T Value
    {
        get
        {
            //Check for the cached value
            if (!this.hasValue)
            {
                //Try to get the value from Isolated Storage
                if (!IsolatedStorageSettings.ApplicationSettings.TryGetValue(this.name, out this.value))
                {
                    //It hasn't been set yet
                    this.value = this.defaultValue;
                    IsolatedStorageSettings.ApplicationSettings[this.name] = this.value;
                }
                this.hasValue = true;
            }
            return this.value;
        }

        set
        {
            //Save the value to Isolated Storage
            IsolatedStorageSettings.ApplicationSettings[this.name] = value;
            this.value = value;
            this.hasValue = true;
        }
    }

    public T DefaultValue
    {
        get { return this.defaultValue; }
    }

    // Clear cached value
    public void ForceRefresh()
    {
        this.hasValue = false;
    }
}

The above Setting.cs class is used to store and retrieve values, and I am using another class called Settings.cs as a mechanism for using those stored values.

Settings.cs

public static Setting<ObservableCollection<BrowserItem>> BrowserList = new Setting<ObservableCollection<BrowserItem>>("Browsers", new ObservableCollection<BrowserItem>());
    public static Setting<string> InitialUri = new Setting<string>("InitialUri", "http://www.bing.com");

In the above, InitialUri may be changed and the value is saved and retrieved correctly. On the other hand, BrowserList (the ObservableCollection of type BrowserItem (a custom class)) is not stored or saved? The following shows how I am attempting to use BrowserList

BrowserItem.cs

[DataContract]
public class BrowserItem

{
    [DataMember]
    public FullWebBrowser Browser
    {
        get;
        set;
    }
    [DataMember]
    public string Url
    {
        get;
        set;
    }
    [DataMember]
    public BitmapImage ImageUri
    {
        get;
        set;
    }
    [DataMember]
    public string Title
    {
        get;
        set;
    }
    [DataMember]
    public string Notification
    {
        get;
        set;
    }
    [DataMember]
    public bool DisplayNotification
    {
        get
        {
            return !string.IsNullOrEmpty(this.Notification);
        }
    }
    [DataMember]
    public string Message
    {
        get;
        set;
    }
    [DataMember]
    public string GroupTag
    {
        get;
        set;
    }
    [DataMember]
    //for translation purposes (bound to HubTile Title on MainPage) 
    public string TileName
    {
        get;
        set;
    }
}

TabsPage.xaml.cs

void addNew_Click(object sender, EventArgs e)
    {
        BitmapImage newTileImage = new BitmapImage();

        var newItem = new BrowserItem() { Browser = new FullWebBrowser(), Url = "http://www.bing.com", ImageUri = newTileImage, Title = "new", /*Notification = "",*/ Message = "new browser", GroupTag = "TileGroup", TileName = "new" };
        newItem.Browser.InitialUri = Settings.InitialUri.Value; //set the initial uri when created
        Settings.BrowserList.Value.Add(newItem); //update saved BrowserList
    }

In the addNew_Click even handler, the new BrowserItem named newItem is successfully added. However when the app closes or reopens, I check the BrowserList to see if items exist, and if they do I would like to load a specific one based on the items index value in the ObservableCollection. Everytime I perform the check, BrowserList has no saved items? How can I properly save these values in the collection so that they will persist?

Matthew
  • 3,976
  • 15
  • 66
  • 130

1 Answers1

0

This is likely due to serialization failing for the type contained in the observable collection. First, your BrowserItem type needs to be marked as serializable by implementing inheritance of a serialization interface, or applying the [Serializable] attribute:

[Serializable]
public class BrowserItem
{

}

If, in fact, BrowserItem (or any other type you are attempting to save to settings) IS serializable, then you may be assisted by this Q/A.

As well, if your type is already serializable, you might want to serialize a sample of the collection to disk in an xml file, so you can manually/visually inspect what, if anything, might be causing the problem when your type is serialized/deserialized

Community
  • 1
  • 1
dylansweb
  • 674
  • 4
  • 8
  • Ok, what do I have to reference in my project to use `Serializable` – Matthew Sep 25 '12 at 04:42
  • The attribute is: System.SerializableAttribute, so as long as: using System; is at the top of your class file, you can decorate your class definition with [Serializable]. – dylansweb Sep 25 '12 at 04:49
  • OK, I am using .NET for the Windows Phone, so I had to reference System.Runtime.Serialization and instead use [DataContract] instead of [Serialization]. I added my `BrowserItem` custom class above, although I am not sure if I am doing this correctly? `ObservableColletion` still does not get saved values. – Matthew Sep 25 '12 at 05:12
  • Nicely done. Now, I think you need to store your bitmapimage property as an array of bytes (byte[]), for it to be properly serialized..this could be part of it...that and/or the 'FullWebBrowser' type you have a property for is not marked serializable? Is 'FullWebBrowser' a class you defined somewhere? If so, make sure it is also serializable. – dylansweb Sep 25 '12 at 06:54
  • For storing your bitmapimage as bytes, have a look at this: http://stackoverflow.com/questions/4308777/wpf-bitmapimage-serialization-deserialization – dylansweb Sep 25 '12 at 06:55
  • and this: http://stackoverflow.com/questions/10783647/method-to-serialize-a-class-which-contain-bitmapimage-using-2-inherited-class – dylansweb Sep 25 '12 at 06:55
  • Ok to make things a little more simple, I removed the BitmapImage part of the `BrowserItem` class. I also added `[DataContract]` to the top of my `FullWebBrowser` user control. Still it is not working. I'm at a loss to find what is going wrong here, I am not getting any errors during debugging. – Matthew Sep 25 '12 at 19:03
  • If you could create a small test class and/or project, to serialize one of your instances to an xml file, that might reveal the issue..? If you can do that, and don't see something obvious, post the serialized output to here..and let's have a look... – dylansweb Sep 25 '12 at 20:10
  • I just loaded what I have so far in my skydrive account. If you'd like to take a look and see what I'm doing wrong, I would greatly appreciate it. https://skydrive.live.com/redir?resid=6737F11923344D1C!134 – Matthew Sep 25 '12 at 21:12
  • Yes, sure, I can take a look tonight...on my night-shift :-) – dylansweb Sep 25 '12 at 22:12
  • OK, I took that look. Your FullWebBrowser, it is a user control, you should not mark it with DataContract. Instead, you should add more properties to BrowserItem, one for each of the things you need to "remember" a FullWebBrowser by. Then, make sure you can re-create a FullWebBrowser using those properties by creating a constructor on FullWebBrowser for that purpose. If you need to remember more than a few things...consider making a class to encapsulate them, and having a property for that in BrowserItem instead. If it is not clear what I mean, just ask for clarifications. Good Luck! – dylansweb Sep 27 '12 at 08:38