对以前类的反序列化实现INotifiyPropertyChanged

时间:2016-11-01 16:24:04

标签: c# wpf serialization deserialization inotifypropertychanged

我在实现serialization事件的INotifyPropertyChanged个类中遇到了一些问题。 (Binary Serialization of ViewModel (ObservableCollection)

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的目标,可以吗?因为如果我这样做,我可以将我的信息写入任何文本文件,其中包含简单的文本,说明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 个答案:

答案 0 :(得分:1)

他们不会开火,因为没有订阅他们。在WPF中,框架将在加载视图或控件时在后台绑定期间进行订阅。由于您在管道的不同阶段执行此操作,因此您必须找到一种更好的方法来在正确的阶段加载模型,以便再次进行订阅。很难说没有看到更多,但这是非常臭。这是一个控件还是全视图的datacontext?

至少,强制重新塑造模型。否则,可能会序列化dto而不是注入viewmodel并在加载视图之前使用它来恢复状态,或者为主视图模型提供一个接受dto并将其重新绑定到observable属性的方法。就像我说的那样,如果没有看到你真正在做的事情,很难说。