我在实现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
}
}
答案 0 :(得分:1)
他们不会开火,因为没有订阅他们。在WPF中,框架将在加载视图或控件时在后台绑定期间进行订阅。由于您在管道的不同阶段执行此操作,因此您必须找到一种更好的方法来在正确的阶段加载模型,以便再次进行订阅。很难说没有看到更多,但这是非常臭。这是一个控件还是全视图的datacontext?
至少,强制重新塑造模型。否则,可能会序列化dto而不是注入viewmodel并在加载视图之前使用它来恢复状态,或者为主视图模型提供一个接受dto并将其重新绑定到observable属性的方法。就像我说的那样,如果没有看到你真正在做的事情,很难说。