1

I've tried following the steps in Joost Van Schaik's article on tombstoning but was unable to get it to work for me. I'm no doubt doing something wrong. In my ViewModel:

private string _foobar ="init";

public string testStr
{
    get
    {
        return _foobar;
    }

    set
    {
        _foobar = value;
    }
}

And in my page:

<TextBox x:Name="tBoxTest" Text="{Binding testStr, Mode=TwoWay}" />

While the application is running, changing the value in tBoxTest sets _foobar just fine, but try to serialize it and it’s as if it has forgotten the instance??? Any help would be greatly appreciated.

Stonetip
  • 1,150
  • 10
  • 20
  • You've shown the code for your property, which looks fine, but have you implemented the rest of the solution to actually serialize and deserialize the instance of your view model accordingly in the `Activated` and `Deactivated` events? – Derek Lakin Feb 02 '11 at 08:11
  • Yes, I have. I should have made that clear in this post. I was trying to focus on the one area which is a problem. – Stonetip Feb 02 '11 at 14:46

2 Answers2

1

I was able to get tombstoning to work, along with having an object be visible to all my ViewModels, by doing the following:

In a Model class, I added:

private static Model1 _instance;
public static Model1 Instance
{
    get { return _instance; }
    set { _instance = value; }
}

public static void CreateNew()
{
    if (_instance == null)
    {
        _instance = new Model1();

        _instance.FirstString = "init";
    }
}

Then in ApplicationExtensions.cs I added:

  public static void SaveToIsolatedStorage(this Application app, Model1 model)
    {
        var dataFileName = GetIsFile((model.GetType()));
        using (var userAppStore =
                 IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (userAppStore.FileExists(dataFileName))
            {
                userAppStore.DeleteFile(dataFileName);
            }
            using (var iss = userAppStore.CreateFile(dataFileName))
            {
                SilverlightSerializer.Serialize(model, iss);
            }
        }
    }

And in App.xaml.cs I changed LoadModel() to:

private void LoadModel()
{
    try
    {
        Model1.Instance = this.RetrieveFromIsolatedStorage<Model1>();
    }
    catch (Exception) { }

    if (Model1.Instance == null) Model1.CreateNew();
}

That all made things like this work in my ViewModel files:

public string TestStr
{
    get
    {
        return Model1.Instance.FirstString;
    }

    set
    {
        Model1.Instance.FirstString = value;
    }
}

And by that, I mean that the Model1 object is getting serialized and tombstoning is working - at least I’m getting what I think I want. I’ve tested it a lot by navigating between apps, phone settings, turning the phone off and on, locking it and calling it while in the app from another phone. Performance when deserializing is great. And I can work with the vars.

That said, Mr. Van Schaik replied to a request for assistance with: "If you are subclassing from an MVVMLight ViewModelBase it does, and then you should call RaisePropertyChanged from your setter like this:

private string _foobar ="init";

public string TestStr { get { return _foobar; }

    set
    {
         RaisePropertyChanged("TestStr");
        _foobar = value;
    }
}

RaisePropertyChanged notifies any listenings views (i.e. the TextBox you bound to it) that a property is changed and that the should update their contents. This is a crucial mechanism."

So I will work with what I was originally trying but with the addition of RaisePropertyChanged to see what that does.

UPDATE

Although I implemented RaisedPropertyChanged (using the code snippet mvvminpc) in my MainViewModel.cs file, that still had no effect (as good as it may be for other things) on serializing anything created within the ViewModel. I'm probably still doing something wrong, but it may also be because view models inherit from a protected class (answer from Laurent Bugnion). I (very reluctantly) tried changing that class from protected to public and recompiling, but it didn't help in my case and I hate to fork a referenced library like that. Anyway, I'm just forging ahead for now with creating the Model1 instance in App.xaml.cs. Seems to work. While I was at it, I modified one of Van Schaik's methods to accept any type of object:

public static void SaveToIsolatedStorage<T>(this Application app, T obj)
where T : class
{
    var dataFileName = GetIsFile(typeof(T));
    using (var userAppStore =
                IsolatedStorageFile.GetUserStoreForApplication())
    {
        if (userAppStore.FileExists(dataFileName))
        {
            userAppStore.DeleteFile(dataFileName);
        }
        using (var iss = userAppStore.CreateFile(dataFileName))
        {
            SilverlightSerializer.Serialize(obj, iss);
        }
    }
}
Community
  • 1
  • 1
Stonetip
  • 1,150
  • 10
  • 20
0

From the code you've posted there isn't an instant answer.

My advice to debug this is:

  • if you've copied the code exactly from that article then add something (a messagebox?) to the empty catch handler - `catch (Exception){ }

  • use the debugger to put breakpoints in the LoadModel and SaveToIsolatedStorage methods

  • use these breakpoints to step through the Load and Save code - is the code correctly loading and saving?

To be honest, with problems like this, doing a little investigation yourself is much better than asking questions on here (IMO!)

Stuart
  • 66,722
  • 7
  • 114
  • 165
  • I'm new to posting on Stack Overflow, so let me just mention that I will never post a question unless I've tried everything else. I did all those things mentioned above, Googled the daylights out of it and downloaded and hunted through 6 samples I found. I even considered switching over to Caliburn Micro, since it did have a solution. But I like MVVM-Light and have invested time in it already. My assumption in posting just that code was that someone else would have done all the steps in the article. Read the post below for one solution and further investigation on my part. – Stonetip Feb 02 '11 at 14:51
  • I guess that would be the post above where I provided an answer. (Rather than just add to my original post, I chose to answer it because, well, that is an answer to the problem. – Stonetip Feb 02 '11 at 15:09
  • Cool - I'm new too - just thought that in this case the best advice was to put in some breakpoints to identify where things were going wrong. Hope the advice helped. – Stuart Feb 02 '11 at 16:19
  • Sorry, not meaning to rag on you. In fact, I greatly appreciate your answer on a previous question of mine. – Stonetip Feb 02 '11 at 18:26