There is such a class:

public class ChapterCollection : ObservableCollection<ChapterVM> { public bool? IsSelectedAll { get { return _isSelectedAll; } set { _isSelectedAll = value; OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsSelectedAll))); } } } 

When it is serialized in XML, the IsSelectedAll property IsSelectedAll not serialized. Only a collection of ChapterVM objects.

How to serialize a property?


Serialization is as follows:

 public static void SerializeToXml(string path, object saveObject) { var formatter = new XmlSerializer(saveObject.GetType()); using (FileStream fs = new FileStream(path, FileMode.Create)) { formatter.Serialize(fs, saveObject); } } 
  • 3
    how do you serialize? - Grundy
  • @Gardes, can you explain why editing the title? You want to say that the problem is in the Nullable type and if you replace it with a regular bool problem goes away? - Andrew NOP
  • Collections are usually not a good place for additional properties. In addition, during serialization, these properties will be ignored if the object being serialized looks like a collection. - sp7
  • @ sp7, do you recommend using author composition instead of inheritance? - Andrew NOP
  • 2
    @Andrey, in this case, yes. It is easier to create a certain wrapper in which to put its current collection and this property, and then serialize this object. - sp7

1 answer 1

The simplest solution is to reject inheritance in favor of composition. Indeed, it is logical to assume that the ChapterCollection not just "is" a collection of the ChapterVM , but contains a collection of the ChapterVM and also some other properties, as a sign of selected elements of the collection, etc.
Shl. No wonder smart design books write

Prefer composition to inheritance


If, however, you intend to leave inheritance, you need to implement the IXmlSerializable interface to override the actions of the serializer. You can do it like this:

 public class ChapterCollection : ObservableCollection<Chapter>, IXmlSerializable { bool? _isSelectedAll; public bool? IsSelectedAll { get { return _isSelectedAll; } set { _isSelectedAll = value; OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsSelectedAll))); } } public XmlSchema GetSchema() => null; public void ReadXml(XmlReader reader) { reader.ReadStartElement(); // Читаем из потока дополнительные свойства вручную IsSelectedAll = reader.ReadElementContentAsBoolean(nameof(IsSelectedAll), ""); // Читаем элементы коллекции XmlSerializer ser = new XmlSerializer(typeof(Chapter)); while (reader.NodeType == XmlNodeType.Element) Add((Chapter)ser.Deserialize(reader)); reader.ReadEndElement(); } public void WriteXml(XmlWriter writer) { // Сериализуем дополнительные свойства вручную writer.WriteStartElement(nameof(IsSelectedAll)); writer.WriteValue(IsSelectedAll); writer.WriteEndElement(); // Сериализуем элементы коллекции XmlSerializer ser = new XmlSerializer(typeof(Chapter)); foreach (var ch in this) ser.Serialize(writer, ch); } } 

I will add the answer option of serialization at a composition.

Our collection class turns into this:

 public class ChapterCollection { public bool? IsSelectedAll { get; set; } public ObservableCollection<Chapter> Collection { get; } = new ObservableCollection<Chapter>(); } 

Note that you must create an instance manually, the serializer cannot create "custom" collections, so it will not fill it: = new ObservableCollection<Chapter>();
But it is not necessary to open the collection property for writing ( set; ).

Now you can use Linq , but you have to specify the name of this collection property:

 myChapterCollection.Collection.Select(...); 

If you implement IEnumerable<> , then the serializer will again begin to think that it is a collection and will lose properties, moreover, it will require you to implement the untyped Add(object) method, which is already ugly and adds some fragility.

PS: thanks to C # duck typing, you can still add a small piece of sugar, adding a method to the class:

 public IEnumerator<Chapter> GetEnumerator() => ((IEnumerable<Chapter>)Collection).GetEnumerator(); 

although this will not allow using LINQ on an instance of a class, it will simplify the foreach code:

 // myChapterCollection.Collection писать не требуется: foreach (var chapter in myChapterCollection) ... 
  • @Andrey, And how to serialize a property during composition? Marked with attribute [XmlElement] - did not help. - trydex
  • What error gives? - Andrew NOP
  • There was no error. I believe that this was due to the implementation of the IEnumerable interface, so that LINQ methods are available. - trydex
  • @maxwell, the question is closed, did I understand correctly? - Andrei NOP
  • one
    @maxwell, supplemented the answer with a variant of serialization with the composition - Andrey NOP