Есть такой класс:
public class ChapterCollection : ObservableCollection<ChapterVM>
{
public bool? IsSelectedAll
{
get { return _isSelectedAll; }
set
{
_isSelectedAll = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsSelectedAll)));
}
}
}
При его сериализации в XML свойство IsSelectedAll не сериализуется. Только коллекция объектов ChapterVM.
Как сериализовать свойство?
Сериализация происходит так:
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);
}
}
Наиболее простым решением является отказ от наследования в пользу композиции. Действительно, логично предположить что ChapterCollection не просто "является" коллекцией ChapterVM, а содержит в себе коллекцию ChapterVM и также некоторые другие свойства, как признак выделенности элементов коллекции и т.п.
Зы. Недаром умные книги по проектированию пишут
Предпочитайте композицию наследованию
Если всё же вы намерены оставить наследование, для переопределения действий сериализатора необходимо реализовать интерфейс IXmlSerializable. Сделать это можно примерно так:
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);
}
}
Дополню ответ вариантом сериализации при композиции.
Наш класс коллекции превращается в такой:
public class ChapterCollection
{
public bool? IsSelectedAll { get; set; }
public ObservableCollection<Chapter> Collection { get; } = new ObservableCollection<Chapter>();
}
Обратите внимание, создать экземпляр нужно обязательно вручную, сериализатор не может создавать "кастомные" коллекции, поэтому он не заполнит ее: = new ObservableCollection<Chapter>();
Но зато открывать свойство коллекции на запись (set;) не нужно.
Теперь вы можете использовать Linq, но придется указать имя этого свойства-коллекции:
myChapterCollection.Collection.Select(...);
Если вы реализуете IEnumerable<>, то сериализатор опять начнет думать что это коллекция и потеряет свойства, да еще к тому же потребует реализовать нетипизированный метод Add(object), что уже некрасиво и добавляет некоторую хрупкость.
PS: благодаря утиной типизации C# можно все же добавить маленький кусочек сахара, добавив в класс метод:
public IEnumerator<Chapter> GetEnumerator()
=> ((IEnumerable<Chapter>)Collection).GetEnumerator();
это хоть и не даст воспользоваться Linq на экземпляре класса, но позволит упростить код foreach:
// myChapterCollection.Collection писать не требуется:
foreach (var chapter in myChapterCollection)
...
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости