如何实现可以保存在用户设置中的 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&lt;EQLControls.Controls.SoundViewModel&gt;" 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>{}