Serializing Microsoft.Toolkit.Mvvm ObservableRecipient/Observable Objects

Andrew Azz 171 Reputation points
2021-02-24T22:27:11.963+00:00

I have a WPF application that is trying to follow the mvvm pattern. The model objects are held in ObservableCollections, as properties of the viewmodel.
In previous use, I subclassed from the ObservableCollection, and inherited from that; thereby allowing the addition of any necessary Serialisation/Datacontract attributes.

I wondered if this was also a correct approach to use with the ObservableRecipient/Observable objects that are a part of the community toolkit, or is there a better way of serialising the models?

Relatedly, in the previous versions I have put the serialise/deserialise functionality into a Viewmodel method. I'm not sure that was properly following the mvvm pattern, and instead should of been using a Service (or something). Though when it comes down to it, I cannot see how the VM method approach is breaking the mvvm rules.

Generally, my question is whether Microsoft.Toolkit.Mvvm has a best practices when it comes to persisting model data?

XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
778 questions
{count} votes

Accepted answer
  1. Andrew Azz 171 Reputation points
    2021-02-26T10:33:49.497+00:00

    @DaisyTian-MSFT

    No need. My mistake was using the [DataContract] attribute in the first place!

    Apparently since .NET 3.5 SP1 (4836803), the [DataContract] attribute is not required for serialisation with the DataContractSerializer, and applying it was the only reason the error was occurring. It also seems the [DataMember] is accepted without the [DataContract], so private fields can also be serialised (though I've not tried to actually test this - I just added the attribute and the object serialisation worked).

    If Microsoft had made this nearly decade old change clear in their documentation system.runtime.serialization.datacontractserializer, then there would not have been a problem. Instead their example shows:

       // You must apply a DataContractAttribute or SerializableAttribute  
        // to a class to have it serialized by the DataContractSerializer.  
        [DataContract(Name = "Customer", Namespace = "http://www.contoso.com")]  
        class Person : IExtensibleDataObject  
    

    Thank you for pointing me to the correct forum - I did not know about it, and will ask future questions there.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Andrew Azz 171 Reputation points
    2021-02-25T09:51:04.027+00:00

    @DaisyTian-MSFT It is correct that the Microsoft.Toolkit.Mvvm is essentially UWP; however, it can also be used in a WPF project which uses host-standard-control-with-xaml-islands.
    I am using it because the previously employed www.mvvmlight.net is depreciated.

    In my viewmodels there are collections of model objects:

            public class ResearchObjectsViewModel : Observable  
            {  
                public ResearchObjectsViewModel()  
                {  
                    InitialiseView();  
                }    
                     
                ObservableCollection<SearchObject> searchObjects = new ObservableCollection<SearchObject>();  
                public ObservableCollection<SearchObject> SearchObjects  
                {  
                    get => searchObjects;  
                    set  
                    {  
                        searchObjects = value;  
                        this.OnPropertyChanged(nameof(this.SearchObjects));  
                    }  
                 }  
                .....  
            }  
    

    and the model objects themselves are also observable:

      public class SearchObject : ObservableRecipient  
        {  
      
            public SearchObject()  
            {  
            }  
          .....  
       }  
    

    The data held in the models' properties may be downloaded, or entered by the user. When the app is shut down, the data are lost, so some form of serialisation is necessary in order to store the data to disk.

    In order to use any existing functionality for doing this, such as how-to-serialize-and-deserialize-json-data an attribute must be applied to the class to be serialised. If [DataContract] is applied to SearchObject then it is disallowed, since the base class ObservableRecipient has no attributes. The same problem occurs with the observable collections - and in the past this was circumvented via subclassing, allowing the [Serializable] to be applied:

        [Serializable]  
        public class SObservableCollection<T> : ObservableCollection<T>, INotifyPropertyChanged  
        {  
        ....  
        }  
    

    I am about to implement the same process to the ObservableRecipient class, and just wanted to check if this was not way off base (pardon the pun).
    If it were not possible to do, then it will be a nightmare to custom serialise without using the Microsoft standard serialisers.
    Edit - I seem to have posted this as an answer, rather than a reply to DaisyTian-MSFT. Apologies.

    Update - It does not seem possible to subclass the ObservableRecipient with serialisation attributes. I'm now going to try inheriting from Observable for the models, as do viewmodels. It strikes me as strange, though that the Community would release this toolkit which seems to effectively remove any way to use Microsoft serialisation. What good is that?