如何实现可以保存在用户设置中的类?

时间:2015-04-24 16:59:55

标签: c# wpf serialization settings

我有以下课程 -

[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 ) );
    }
}

我需要将此类保存到应用程序的用户设置中,这就是原因(请不要说"为什么不在每个文件的用户设置中单独创建FileInfo条目class?"):我需要保存这个类的51个单独的条目(一个单独表现为默认,另外50个;每个玩家一个,我 在设置中创建204个条目。

我快速搜索了如何创建一个可以序列化的类,以及我所说的MSDN文章

The easiest way to make a class serializable is to mark it with the Serializable attribute

显然,这不是可以通过“简单方式”完成的事情。

这是我在“用户设置”类中拥有的此条目的代码(以及这些条目的相应列表) -

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类,以便在调用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并将它们的文件名存储在变量中,作为第一个镜头,我接下来会尝试对两个作为字符串执行相同操作。)< / p>

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>

1 个答案:

答案 0 :(得分:1)

SoundViewModel需要一个无参数构造函数来进行反序列化。仅序列化公共属性。您可以使用[XmlIgnore]跳过属性。

您也无法在用户设置中保存通用类型(在您的情况下为Observable<T>)。虽然有一个简单的解决方法,但我经常用词典来做这件事。

[Serializable]
public class MySerializableCollection : List<SoundViewModel>{}