INotifyPropertyChanged
イベントを実装するクラスのserialization
にいくつかの問題がありました。今私はdeserialization
に問題がある以前のクラスの非直列化INotifiyPropertyChangedの実装
SerializationException when serializing instance of a class which implements INotifyPropertyChangedに推奨されているように(Binary Serialization of ViewModel (ObservableCollection))
を解決しました。
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
を発射しないでください。
シリアライズ前と同じ機能を得るにはどうすればよいですか?それは、することができます
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
の目標でcan't:
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:は、今のところ私はこれでそれを行いますか?私がそれをすれば、私は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はDTOオプションに言及しています。シリアライゼーションにDTOを使用するようにこのシステムを再構築すれば、少しのグルーコードを必要とするだけで多くの頭痛を防ぐことができます。 –
あなたは 'DTO'が何であるか説明できますか? (リンクや何かを追加しますか?)何かを変更するときに、少なくともセットのアクセサを使用しないでください。 'ViewModel'が' TreeView'にバインドされています。 – Thoms
ビューモデルのポイントはビューを元に戻すことです.dtoは主に状態を移送するためのものです。 DTOは単なる財産バッグです。プロパティの束を持ち、動作しないオブジェクトです。私はしばしば、あなたが復元しようとしているオブジェクトのカプセル化された動作が、外部ソースに開く必要がないオブジェクトのような状況でこれらを使用します。この場合、DTOを使用してデータをVMにソートすることをソートします。すべての状態情報を含むDTOを渡して、VMが自身の状態を復元し、ビュー上のコントロールへのオブザーバブルの再バインドなどの任意の規則を適用できるようにする – Sinaesthetic