C# 将WPF中的对象序列化为XML
因此,我正在使用MVVM在WPF中构建一个应用程序,并希望将各种对象模型数据保存为XML。使用我可以正确地将对象序列化为XML,但我遇到的问题是MVVM本身。C# 将WPF中的对象序列化为XML,c#,xml,wpf,serialization,mvvm,C#,Xml,Wpf,Serialization,Mvvm,因此,我正在使用MVVM在WPF中构建一个应用程序,并希望将各种对象模型数据保存为XML。使用我可以正确地将对象序列化为XML,但我遇到的问题是MVVM本身。 我无法在ViewModel代码的ICommand段中直接访问对象的模型(例如,当我点击save时,它会转到ViewModel中的ICommand方法)。 我已经将模型设置为可序列化的,我只是无法将其直接传递给我的序列化方法(它包含在它自己的静态助手类中),因此即使我没有收到“意外类型”的回音(因为VieWModel不可序列化),我也会得到
我无法在ViewModel代码的ICommand段中直接访问对象的模型(例如,当我点击save时,它会转到ViewModel中的ICommand方法)。
我已经将模型设置为可序列化的,我只是无法将其直接传递给我的序列化方法(它包含在它自己的静态助手类中),因此即使我没有收到“意外类型”的回音(因为VieWModel不可序列化),我也会得到大量多余的垃圾,而不仅仅是正在序列化的模型类 我不确定我是否只是设计得不正确,或者是否有更好的方法,或者 另外,所有这些字段都只是被写入适当绑定的文本框控件中。现在,我只尝试使用名称字段,以避免其他数据类型无法正常工作时出现任何问题 编辑:根据注释中的要求,现在的目标只是能够在几个文本框(名字、中间名、姓氏)中写入一些文本位,然后将其保存到XML文件中 有关的总结模型:
namespace XMLaw.Model
{
[Serializable]
public class ClientModel
{
private string firstName { get; set; }
private string middleName { get; set; }
private string lastName { get; set; }
private DateTime dateOfBirth { get; set; }
private string ssn { get; set; } //Format: AA ## ## ## A, spaces optional
private string address { get; set; }
private string phone { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#region Name Properties
public string FirstName
{
get { return firstName; }
set
{
if( firstName != value )
{
firstName = value;
OnPropertyChanged("FirstName");
}
}
}
public string MiddleName
{
get { return middleName; }
set
{
if (middleName != value)
{
middleName = value;
OnPropertyChanged("MiddleName");
}
}
}
public string LastName
{
get { return lastName; }
set
{
if (lastName != value)
{
lastName = value;
OnPropertyChanged("LastName");
}
}
}
#endregion
public DateTime DateOfBirth
{
get { return dateOfBirth; }
set
{
if ( dateOfBirth != value )
{
DateTime dt = Convert.ToDateTime(value); //This will probably need to revisited since DateTime objects are fucking stupid
dateOfBirth = dt.Date;
OnPropertyChanged("DateOfBirth");
}
}
}
public string SSN
{
get { return ssn; }
set
{
if( ssn != value)
{
ssn = value;
OnPropertyChanged("SSN");
}
}
}
public string Address
{
get { return address; }
set
{
if( address != value)
{
address = value;
OnPropertyChanged("Address");
}
}
}
public string Phone
{
get { return phone; }
set
{
if( phone != value )
{
phone = value;
OnPropertyChanged("Phone");
}
}
}
}
}
以及所讨论的ViewModel(调用序列化的Save命令位于底部)
还有我无耻地从上面的链接中获取的Serailization方法
public static class Helper
{
public static string Serialize<T>(this T value)
{
if (value == null)
{
return string.Empty;
}
try
{
var xmlserializer = new XmlSerializer(typeof(T));
var stringWriter = new StringWriter();
using (var writer = XmlWriter.Create(stringWriter))
{
xmlserializer.Serialize(writer, value);
return stringWriter.ToString();
}
}
catch (Exception ex)
{
throw new Exception("An error occurred", ex);
}
}
}
公共静态类帮助器
{
公共静态字符串序列化(此T值)
{
如果(值==null)
{
返回字符串。空;
}
尝试
{
var xmlserializer=新的xmlserializer(typeof(T));
var stringWriter=新的stringWriter();
使用(var writer=XmlWriter.Create(stringWriter))
{
serializer.Serialize(writer,value);
返回stringWriter.ToString();
}
}
捕获(例外情况除外)
{
抛出新异常(“发生错误”,例如);
}
}
}
将您的客户机型号更改为:
[Serializable]
public class ClientModel
{
private string firstName;
private string middleName;
private string lastName;
private DateTime dateOfBirth;
private string ssn;
private string address;
private string phone;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#region Name Properties
public string FirstName {
get { return firstName; }
set {
if (firstName != value)
{
firstName = value;
OnPropertyChanged("FirstName");
}
}
}
public string MiddleName {
get { return middleName; }
set {
if (middleName != value)
{
middleName = value;
OnPropertyChanged("MiddleName");
}
}
}
public string LastName {
get { return lastName; }
set {
if (lastName != value)
{
lastName = value;
OnPropertyChanged("LastName");
}
}
}
#endregion
public DateTime DateOfBirth {
get { return dateOfBirth; }
set {
if (dateOfBirth != value)
{
DateTime dt = Convert.ToDateTime(value); //This will probably need to revisited since DateTime objects are fucking stupid
dateOfBirth = dt.Date;
OnPropertyChanged("DateOfBirth");
}
}
}
public string SSN {
get { return ssn; }
set {
if (ssn != value)
{
ssn = value;
OnPropertyChanged("SSN");
}
}
}
public string Address {
get { return address; }
set {
if (address != value)
{
address = value;
OnPropertyChanged("Address");
}
}
}
public string Phone {
get { return phone; }
set {
if (phone != value)
{
phone = value;
OnPropertyChanged("Phone");
}
}
}
}
用法:
var xx = new ClientModel();
xx.FirstName = "John";
xx.LastName = "Smith";
xx.DateOfBirth = DateTime.Now;
var result = xx.Serialize();
public ICommand SaveCommand
{
get
{
if (btnSave == null)
btnSave = new Save();
btnSave.Model = this.ClientModel;
return btnSave;
}
set { btnSave = value; }
}
结果:
http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\“”>
约翰·史密斯
2016-07-11T00:00:00+02:00
编辑:
此代码:
public void Execute(object param)
{
ClientViewModel viewModel = (ClientViewModel)param;
//TODO: Insert XML serialization and save to a file
var xml = Helper.Serialize(param);
//Placeholder to make sure the button works
viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now;
}
应替换为以下内容:
public void Execute(object param)
{
ClientModel model= (ClientModel )param;
//TODO: Insert XML serialization and save to a file
var xml = Helper.Serialize(param);
//Placeholder to make sure the button works
viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now;
}
确保您的Param
为ClientModel类型
我也强烈推荐你,让你了解
编辑2(命令Thingy):
用法:
var xx = new ClientModel();
xx.FirstName = "John";
xx.LastName = "Smith";
xx.DateOfBirth = DateTime.Now;
var result = xx.Serialize();
public ICommand SaveCommand
{
get
{
if (btnSave == null)
btnSave = new Save();
btnSave.Model = this.ClientModel;
return btnSave;
}
set { btnSave = value; }
}
不要将属性用作
属性的支持字段(你真的这样做了吗)。请将你的属性设置为私有的字段。此外,你的属性更改的事件无法序列化。请将其标记为[非序列化]
你能给我一个例子说明你的意思吗“不要使用属性作为属性的支持字段”?这确实是我第一次尝试使用MVVM,我花了很长时间才找到一个不复杂的教程,这是我找到的唯一连贯的方法。@KoalaBear看到它在哪里写着私有字符串firstName{get;set;}
?只要替换{get;set;}
带分号:private string firstName;
。这将属性转换为字段。属性具有get/set访问器;字段只是一个成员变量。无论您试图实现什么,这都不是实现的方法。如果您想描述您的目标,我们可能会为您提供更好、更简单的解决方案。此外,xml serialization在框架中有点糟糕。我总是使用NetDataContractSerializer或XamlServices.Save。它们处理对象图的效果比XmlSerializer好得多。两者都产生XML(第二种是xaml风格的XML).啊,是的。我现在明白我有多傻了。这并不能解决无法从ViewModel类“save”内部序列化对象的问题“但是,命令。后期编辑:无法将类型为'XMLaw.ViewModel.ClientViewModel'的对象强制转换为类型为'XMLaw.Model.ClientModel'。第一步:使用。另一种方法是,在Save
-命令中实现ClientModel
类型的属性,并将其设置为用于purpose@KoalaBear我已经为您做了一个快速而肮脏的修复。我编辑了Save类,使其具有一个接受ClientModel的构造函数,它不允许我以其他方式设置模型变量。我相信这是100%的错误方式做任何事情,但它做了我现在需要的,谢谢你的帮助。我将不得不重新埋头于其他文档中,以降低这一点。