如何实现可以保存在用户设置中的 class?
How can I implement a class that can be saved in User Settings?
我有以下 class -
[Serializable]
public class SoundViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; private set; }
public SoundViewModel( string Name ) { this.Name = Name; }
private FileInfo
_RingIn = new FileInfo( "Sounds/RingIn.wav" ),
_Correct = new FileInfo( "Sounds/Correct.wav" ),
_Incorrect = new FileInfo( "Sounds/Incorrect.wav" ),
_TimeOver = new FileInfo( "Sounds/TimeOver.wav" );
public FileInfo RingIn {
get { return this._RingIn; }
set {
this._RingIn = value;
this.OnPropertyChanged( "RingIn" );
}
}
public FileInfo Correct {
get { return this._Correct; }
set {
this._Correct = value;
this.OnPropertyChanged( "Correct" );
}
}
public FileInfo Incorrect {
get { return this._Incorrect; }
set {
this._Incorrect = value;
this.OnPropertyChanged( "Incorrect" );
}
}
public FileInfo TimeOver {
get { return this._TimeOver; }
set {
this._TimeOver = value;
this.OnPropertyChanged( "TimeOver" );
}
}
private void OnPropertyChanged( string p ) {
if ( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( p ) );
}
}
我需要将此 class 保存到应用程序的用户设置中,原因如下(请不要说 "Why not just make a separate FileInfo
entry in the User Settings for each File in the class?"):我需要保存此 [=62] 的 51 个单独条目=](一个单独作为默认行为,还有 50 个;每个玩家一个,我 not 进入 204 个条目设置。
我快速搜索了如何制作可以序列化的 class,我看到的 MSDN 文章说
The easiest way to make a class serializable is to mark it with the Serializable attribute
显然,这不是 'easy way' 可以做到的事情。
这是我在用户设置 class -
中拥有的此条目(以及这些条目的相应列表)的代码
XML -
<Setting Name="DefaultSounds" Type="EQLControls.Controls.SoundViewModel" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="PlayerSounds" Type="System.Collections.ObjectModel.ObservableCollection<EQLControls.Controls.SoundViewModel>" Scope="User">
<Value Profile="(Default)" />
</Setting>
C# -
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::EQLControls.Controls.SoundViewModel DefaultSounds {
get {
return ((global::EQLControls.Controls.SoundViewModel)(this["DefaultSounds"]));
}
set {
this["DefaultSounds"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Collections.ObjectModel.ObservableCollection<EQLControls.Controls.SoundViewModel> PlayerSounds {
get {
return ((global::System.Collections.ObjectModel.ObservableCollection<EQLControls.Controls.SoundViewModel>)(this["PlayerSounds"]));
}
set {
this["PlayerSounds"] = value;
}
}
如有必要,我可以提供更多详细信息。
如何实现 SoundViewModel class,以便在调用 Settings.Default.Save()
时保存设置?
此外 - 我发现的一个线索是,当我尝试保存时,这是我在用户设置文件中得到的:
<EQLControls.Properties.Settings>
<setting name="DefaultSounds" serializeAs="Xml">
<value />
</setting>
<setting name="PlayerSounds" serializeAs="Xml">
<value />
</setting>
</EQLControls.Properties.Settings>
编辑
有人建议我使用文件名而不是 FileInfo
对象。
我尝试了这个但它没有用 - (我将属性保留为 FileInfo
并将它们的文件名存储在变量中,作为第一枪,我接下来将尝试对两个字符串做同样的事情)。
public class SoundViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; private set; }
public SoundViewModel( string Name ) { this.Name = Name; }
private string
_RingIn = "Sounds/RingIn.wav",
_Correct = "Sounds/Correct.wav",
_Incorrect = "Sounds/Incorrect.wav",
_TimeOver = "Sounds/TimeOver.wav";
public FileInfo RingIn {
get { return new FileInfo(this._RingIn ?? "Sounds/RingIn.wav"); }
set {
this._RingIn = value.FullName;
this.OnPropertyChanged( "RingIn" );
}
}
public FileInfo Correct {
get { return new FileInfo(this._Correct ?? "Sounds/Correct.wav"); }
set {
this._Correct = value.FullName;
this.OnPropertyChanged( "Correct" );
}
}
public FileInfo Incorrect {
get { return new FileInfo(this._Incorrect ?? "Sounds/Incorrect.wav"); }
set {
this._Incorrect = value.FullName;
this.OnPropertyChanged( "Incorrect" );
}
}
public FileInfo TimeOver {
get { return new FileInfo(this._TimeOver ?? "Sounds/TimeOver.wav"); }
set {
this._TimeOver = value.FullName;
this.OnPropertyChanged( "TimeOver" );
}
}
private void OnPropertyChanged( string p ) {
if ( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( p ) );
}
}
编辑 2
我删除了 FileInfo 属性并替换为字符串:
public class SoundViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; private set; }
public SoundViewModel( string Name ) { this.Name = Name; }
private string
_RingIn = "Sounds/RingIn.wav",
_Correct = "Sounds/Correct.wav",
_Incorrect = "Sounds/Incorrect.wav",
_TimeOver = "Sounds/TimeOver.wav";
public string RingIn {
get { return this._RingIn; }
set {
this._RingIn = value;
this.OnPropertyChanged( "RingIn" );
}
}
public string Correct {
get { return this._Correct; }
set {
this._Correct = value;
this.OnPropertyChanged( "Correct" );
}
}
public string Incorrect {
get { return this._Incorrect; }
set {
this._Incorrect = value;
this.OnPropertyChanged( "Incorrect" );
}
}
public string TimeOver {
get { return this._TimeOver; }
set {
this._TimeOver = value;
this.OnPropertyChanged( "TimeOver" );
}
}
private void OnPropertyChanged( string p ) {
if ( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( p ) );
}
}
还是没有爱,保存的user.config文件很空
<EQLControls.Properties.Settings>
<setting name="PlayerSounds" serializeAs="Xml">
<value />
</setting>
</EQLControls.Properties.Settings>
SoundViewModel
需要一个无参数的构造函数来反序列化。只有 public 个属性将被序列化。您可以使用 [XmlIgnore]
.
跳过属性
您也无法在用户设置中保存通用类型(Observable<T>
在您的情况下)。不过有一个简单的解决方法,我经常用字典来做。
[Serializable]
public class MySerializableCollection : List<SoundViewModel>{}
我有以下 class -
[Serializable]
public class SoundViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; private set; }
public SoundViewModel( string Name ) { this.Name = Name; }
private FileInfo
_RingIn = new FileInfo( "Sounds/RingIn.wav" ),
_Correct = new FileInfo( "Sounds/Correct.wav" ),
_Incorrect = new FileInfo( "Sounds/Incorrect.wav" ),
_TimeOver = new FileInfo( "Sounds/TimeOver.wav" );
public FileInfo RingIn {
get { return this._RingIn; }
set {
this._RingIn = value;
this.OnPropertyChanged( "RingIn" );
}
}
public FileInfo Correct {
get { return this._Correct; }
set {
this._Correct = value;
this.OnPropertyChanged( "Correct" );
}
}
public FileInfo Incorrect {
get { return this._Incorrect; }
set {
this._Incorrect = value;
this.OnPropertyChanged( "Incorrect" );
}
}
public FileInfo TimeOver {
get { return this._TimeOver; }
set {
this._TimeOver = value;
this.OnPropertyChanged( "TimeOver" );
}
}
private void OnPropertyChanged( string p ) {
if ( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( p ) );
}
}
我需要将此 class 保存到应用程序的用户设置中,原因如下(请不要说 "Why not just make a separate FileInfo
entry in the User Settings for each File in the class?"):我需要保存此 [=62] 的 51 个单独条目=](一个单独作为默认行为,还有 50 个;每个玩家一个,我 not 进入 204 个条目设置。
我快速搜索了如何制作可以序列化的 class,我看到的 MSDN 文章说
The easiest way to make a class serializable is to mark it with the Serializable attribute
显然,这不是 'easy way' 可以做到的事情。
这是我在用户设置 class -
中拥有的此条目(以及这些条目的相应列表)的代码XML -
<Setting Name="DefaultSounds" Type="EQLControls.Controls.SoundViewModel" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="PlayerSounds" Type="System.Collections.ObjectModel.ObservableCollection<EQLControls.Controls.SoundViewModel>" Scope="User">
<Value Profile="(Default)" />
</Setting>
C# -
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::EQLControls.Controls.SoundViewModel DefaultSounds {
get {
return ((global::EQLControls.Controls.SoundViewModel)(this["DefaultSounds"]));
}
set {
this["DefaultSounds"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Collections.ObjectModel.ObservableCollection<EQLControls.Controls.SoundViewModel> PlayerSounds {
get {
return ((global::System.Collections.ObjectModel.ObservableCollection<EQLControls.Controls.SoundViewModel>)(this["PlayerSounds"]));
}
set {
this["PlayerSounds"] = value;
}
}
如有必要,我可以提供更多详细信息。
如何实现 SoundViewModel class,以便在调用 Settings.Default.Save()
时保存设置?
此外 - 我发现的一个线索是,当我尝试保存时,这是我在用户设置文件中得到的:
<EQLControls.Properties.Settings>
<setting name="DefaultSounds" serializeAs="Xml">
<value />
</setting>
<setting name="PlayerSounds" serializeAs="Xml">
<value />
</setting>
</EQLControls.Properties.Settings>
编辑
有人建议我使用文件名而不是 FileInfo
对象。
我尝试了这个但它没有用 - (我将属性保留为 FileInfo
并将它们的文件名存储在变量中,作为第一枪,我接下来将尝试对两个字符串做同样的事情)。
public class SoundViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; private set; }
public SoundViewModel( string Name ) { this.Name = Name; }
private string
_RingIn = "Sounds/RingIn.wav",
_Correct = "Sounds/Correct.wav",
_Incorrect = "Sounds/Incorrect.wav",
_TimeOver = "Sounds/TimeOver.wav";
public FileInfo RingIn {
get { return new FileInfo(this._RingIn ?? "Sounds/RingIn.wav"); }
set {
this._RingIn = value.FullName;
this.OnPropertyChanged( "RingIn" );
}
}
public FileInfo Correct {
get { return new FileInfo(this._Correct ?? "Sounds/Correct.wav"); }
set {
this._Correct = value.FullName;
this.OnPropertyChanged( "Correct" );
}
}
public FileInfo Incorrect {
get { return new FileInfo(this._Incorrect ?? "Sounds/Incorrect.wav"); }
set {
this._Incorrect = value.FullName;
this.OnPropertyChanged( "Incorrect" );
}
}
public FileInfo TimeOver {
get { return new FileInfo(this._TimeOver ?? "Sounds/TimeOver.wav"); }
set {
this._TimeOver = value.FullName;
this.OnPropertyChanged( "TimeOver" );
}
}
private void OnPropertyChanged( string p ) {
if ( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( p ) );
}
}
编辑 2
我删除了 FileInfo 属性并替换为字符串:
public class SoundViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; private set; }
public SoundViewModel( string Name ) { this.Name = Name; }
private string
_RingIn = "Sounds/RingIn.wav",
_Correct = "Sounds/Correct.wav",
_Incorrect = "Sounds/Incorrect.wav",
_TimeOver = "Sounds/TimeOver.wav";
public string RingIn {
get { return this._RingIn; }
set {
this._RingIn = value;
this.OnPropertyChanged( "RingIn" );
}
}
public string Correct {
get { return this._Correct; }
set {
this._Correct = value;
this.OnPropertyChanged( "Correct" );
}
}
public string Incorrect {
get { return this._Incorrect; }
set {
this._Incorrect = value;
this.OnPropertyChanged( "Incorrect" );
}
}
public string TimeOver {
get { return this._TimeOver; }
set {
this._TimeOver = value;
this.OnPropertyChanged( "TimeOver" );
}
}
private void OnPropertyChanged( string p ) {
if ( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( p ) );
}
}
还是没有爱,保存的user.config文件很空
<EQLControls.Properties.Settings>
<setting name="PlayerSounds" serializeAs="Xml">
<value />
</setting>
</EQLControls.Properties.Settings>
SoundViewModel
需要一个无参数的构造函数来反序列化。只有 public 个属性将被序列化。您可以使用 [XmlIgnore]
.
您也无法在用户设置中保存通用类型(Observable<T>
在您的情况下)。不过有一个简单的解决方法,我经常用字典来做。
[Serializable]
public class MySerializableCollection : List<SoundViewModel>{}