0

У меня были проблемы с serialization моих классов, реализующих INotifyPropertyChanged событий. (Binary Serialization of ViewModel (ObservableCollection))Deserialization ранее классов Внедрение INotifiyPropertyChanged

решаемая, как рекомендовано в SerializationException when serializing instance of a class which implements INotifyPropertyChanged

Теперь у меня есть проблемы с deserialization. Когда это делать, как

BinaryFormatter formatter = new BinaryFormatter();    
     FileStream fs_open = new FileStream(@"C:\Users\vm_user\Documents\Visual Studio 2015\testbin.txt", FileMode.Open); 
     ViewModels.MainViewModel mvm1 = (ViewModels.MainViewModel)formatter.Deserialize(fs_open); 
     fs_open.Close(); 

В deserialized объекты не срабатывают любой events больше.

Что мне нужно сделать, чтобы получить то же функциональное назначение, что и до сериализации? Прямо сейчас я делаю это с этим:

BinaryFormatter formatter = new BinaryFormatter(); 
     ViewModels.MainViewModel mvm1 = new ViewModels.MainViewModel(); 
     FileStream fs_open = new FileStream(@"C:\Users\vm_user\Documents\Visual Studio 2015\testbin.txt", FileMode.Open);    
     foreach (ViewModels.WatchedFile file in ((ViewModels.MainViewModel)formatter.Deserialize(fs_open)).WatchedFiles) 
     { 
      ViewModels.WatchedFile wf = new ViewModels.WatchedFile(file.Name, file.Path, file.Tags, new ObservableCollection<ViewModels.WatchedFile>()); 
      foreach (ViewModels.WatchedFile subs in file.Subs) 
      { 
       wf.Subs.Add(refeshLoadedFiles(subs)); 
      } 
      mvm1.WatchedFiles.Add(wf); 
     } 
     fs_open.Close(); 

и refreshLoadedFiles:

private ViewModels.WatchedFile refeshLoadedFiles(ViewModels.WatchedFile fileSource) 
    { 
     ViewModels.WatchedFile wf = new ViewModels.WatchedFile(fileSource.Name, fileSource.Path, fileSource.Tags, new ObservableCollection<ViewModels.WatchedFile>()); 
     foreach (ViewModels.WatchedFile subs in fileSource.Subs) 
     { 
      wf.Subs.Add(refeshLoadedFiles(subs)); 
     }    
     return wf; 
    } 

Но это не может быть целью serialization, не так ли? Beacause, если я сделаю это таким образом, я могу написать свою информацию в любой текстовый файл с простым текстом, указав type, а затем все остальное ...

Спасибо за вашу помощь.

Это ViewModel (редактировать):

namespace WatchedFile.ViewModels 
{ 
[Serializable()] 
public class ViewModelBase : INotifyPropertyChanged 
{ 
public event PropertyChangedEventHandler PropertyChanged; 

protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
{ 
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 
} 

[Serializable()] 
public class WatchedFile : ViewModelBase 
{ 
#region Name Property 
private String _name = default(String); 
public String Name 
{ 
    get { return _name; } 
    set 
    { 
     if (value != _name) 
     { 
      _name = value; 
      OnPropertyChanged(); 
     } 
    } 
} 
#endregion Name Property 

#region Path Property 
private String _path = default(String); 
public String Path 
{ 
    get { return _path; } 
    set 
    { 
     setDisplayImage(value); 
     if (value != _path) 
     { 
      _path = value; 
      OnPropertyChanged(); 

     } 
    } 
} 
#endregion Path Property 

#region Tags Property 
private ObservableCollection<Tag> _tags = new ObservableCollection<Tag>(); 
public ObservableCollection<Tag> Tags 
{ 
    get { return _tags; } 
    protected set 
    { 
     if (value != _tags) 
     { 
      _tags = value; 
      OnPropertyChanged(); 
     } 
    } 
} 
#endregion Tags Property 

#region Subs Property 
private ObservableCollection<WatchedFile> _subs = new ObservableCollection<WatchedFile>(); 
public ObservableCollection<WatchedFile> Subs 
{ 
    get { return _subs; } 
    protected set 
    { 
     setDisplayImage(Path); 
     if (value != _subs) 
     { 
      _subs = value; 
      _subs.CollectionChanged += _subs_CollectionChanged; 
      OnPropertyChanged(); 
     } 
    } 
} 

private void _subs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
{ 
    Subs = Sort(Subs); 
} 
#endregion Subs Property 

[NonSerialized()] 
private BitmapImage _displayImage = default(BitmapImage); 
public BitmapImage DisplayImage 
{ 
    get { return _displayImage; } 
    protected set 
    { 
     if (value != _displayImage) 
     { 
      _displayImage = value; 
      OnPropertyChanged(); 
     } 
    } 
} 

public WatchedFile(): this(string.Empty,string.Empty,new ObservableCollection<Tag>(),new ObservableCollection<WatchedFile>()) 
{          
} 

public WatchedFile(String name, String path, ObservableCollection<Tag> tags, ObservableCollection<WatchedFile> subitems) 
{ 
    Subs = WatchedFile.Sort(subitems); 
    Name = name; 
    Path = path; 
    Tags = tags; 
} 

public static ObservableCollection<WatchedFile> Sort(ObservableCollection<WatchedFile> files) 
{ 
    if (files == null) 
     return files; 
    ObservableCollection<WatchedFile> filesReturn = new ObservableCollection<ViewModels.WatchedFile>(); 
    WatchedFile[] sortedArray = files.ToArray(); 

    WatchedFile temp; 
    for (int j = 1; j <= sortedArray.Length - 1; j++) 
    { 
     for (int i = j; i > 0; i--) 
     { 
      if (sortedArray[i].Subs != null && sortedArray[i].Subs.Count > 1) 
      { 
       ObservableCollection<WatchedFile> subs = Sort(sortedArray[i].Subs); 
       sortedArray[i].Subs.Clear(); 
       foreach (WatchedFile f in subs) 
        sortedArray[i].Subs.Add(f); 
      } 

      if (sortedArray[i - 1].Subs != null && sortedArray[i - 1].Subs.Count > 1) 
      { 
       ObservableCollection<WatchedFile> subs = Sort(sortedArray[i - 1].Subs); 
       sortedArray[i - 1].Subs.Clear(); 
       foreach (WatchedFile f in subs) 
        sortedArray[i - 1].Subs.Add(f); 
      } 

      if ((sortedArray[i].Name).CompareTo(sortedArray[i - 1].Name) == -1) 
      { 
       temp = sortedArray[i]; 
       sortedArray[i] = sortedArray[i - 1]; 
       sortedArray[i - 1] = temp; 
      } 
      else 
       break; 
     } 
    } 
    filesReturn.Clear(); 
    foreach (WatchedFile f in sortedArray) 
     filesReturn.Add(f); 

    return filesReturn; 
} 
} 

[Serializable()] 
public class Tag 
{ 
public Tag(String value) 
{ 
    Value = value; 
} 
public String Value { get; private set; } 
} 

[Serializable()] 
public class MainViewModel : ViewModelBase 
{ 
public MainViewModel() 
{ 

} 

#region WatchedFiles Property   
private ObservableCollection<WatchedFile> _watchedFiles = new ObservableCollection<WatchedFile>(); 
public ObservableCollection<WatchedFile> WatchedFiles 
{ 
    get { return _watchedFiles; } 
    protected set 
    { 
     if (value != _watchedFiles) 
     { 
      _watchedFiles =WatchedFile.Sort(value);// value; 
      _watchedFiles.CollectionChanged += _watchedFiles_CollectionChanged; 
      OnPropertyChanged(); 
     } 
    } 
} 

private void _watchedFiles_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
{ 
    WatchedFiles = WatchedFile.Sort(WatchedFiles); 
} 
#endregion WatchedFiles Property 
} 
} 

ответ

1

Они не срабатывают, потому что ничего не подписался на них. В WPF структура будет подписываться во время привязки в фоновом режиме при загрузке представления или элемента управления. Поскольку вы делаете это на другом этапе в конвейере, вам нужно будет найти лучший способ загрузить модель на правильной стадии, чтобы подписки повторялись снова. Трудно сказать, не видя больше, но это очень вонючий. Является ли это элементом управления или полнотекстовым представлением?

По крайней мере, принудительно повторите попытку модели. В противном случае, возможно, сериализуйте dto вместо этого и вставьте в модель viewmodel и используйте ее для восстановления состояния перед загрузкой представления или дайте основной модели представления метод, который принимает dto и перепроверяет его с наблюдаемым свойством. Как я уже сказал, трудно сказать, не видя, что вы на самом деле делаете.

+1

+1 для обозначения опции DTO. Переустановка этой системы для использования DTO для сериализации позволит предотвратить множество головных болей за счет всего лишь небольшого количества кода клея. –

+0

Можете ли вы объяснить, что такое 'DTO'? (добавьте ссылку или что-то в этом роде), и не следует ли это делать/использовать приставные устройства при изменении чего-то? (добавлен вопрос 'ViewModel' на вопрос),' ViewModel' привязан к 'TreeView' – Thoms

+0

Точка модели просмотра - это обратный просмотр, dto в первую очередь предназначен для транспортировки состояния. DTO - всего лишь мешок для вещей; объект с кучей свойств и никакого поведения. Я часто использую их для таких ситуаций, когда объект, состояние которого вы пытаетесь восстановить, имеет инкапсулированное поведение, которое вы обычно не хотите открывать внешним источникам. Поэтому в этом случае вы должны использовать DTO для восстановления данных на виртуальной машине. Передайте ему DTO, содержащий всю информацию о состоянии, и позвольте VM восстановить свое собственное состояние и обеспечить соблюдение любых правил, таких как переплетение наблюдаемых элементов управления в представлении – Sinaesthetic