C# WPF MVVM结构中数据源的XML
在设计WPF应用程序时,我正在学习MVVM模式。到目前为止,我正在学习一个非常好的教程,但是他们在ViewModel的构造函数中填充了模型数据。在本教程中提到,在现实世界中,数据将从数据库或XML文件中提供。我真的很想知道如何使用XML文件填充模型数据,因为我讨厌代码中有硬编码的值 这是我的模型C# WPF MVVM结构中数据源的XML,c#,wpf,mvvm,C#,Wpf,Mvvm,在设计WPF应用程序时,我正在学习MVVM模式。到目前为止,我正在学习一个非常好的教程,但是他们在ViewModel的构造函数中填充了模型数据。在本教程中提到,在现实世界中,数据将从数据库或XML文件中提供。我真的很想知道如何使用XML文件填充模型数据,因为我讨厌代码中有硬编码的值 这是我的模型 namespace MVVM_Basics.Models { using System; using System.ComponentModel; //need to imple
namespace MVVM_Basics.Models
{
using System;
using System.ComponentModel;
//need to implement the interface INotifyPropertyChange, because this is how WPF does it's data binding.
public class Customer : INotifyPropertyChanged
{
/// <summary>
/// Initializing a new instance of the Customer class
/// </summary>
//this is a default constructor for the Customer class
public Customer(String customerName)
{
Name = customerName;
}
private string _Name;
/// <summary>
/// Gets or Sets the Customers Name
/// </summary>
public String Name
{
get{ return _Name;}
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
namespace MVVM\u Basics.Models
{
使用制度;
使用系统组件模型;
//需要实现接口INotifyPropertyChange,因为这是WPF进行数据绑定的方式。
公共类客户:INotifyPropertyChanged
{
///
///初始化Customer类的新实例
///
//这是Customer类的默认构造函数
公共客户(字符串客户名称)
{
名称=客户名称;
}
私有字符串\u名称;
///
///获取或设置客户名称
///
公共字符串名
{
获取{return\u Name;}
设置
{
_名称=值;
不动产变更(“名称”);
}
}
公共事件属性更改事件处理程序属性更改;
私有void OnPropertyChanged(字符串propertyName)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
}
这是ViewModel
using MVVM_Basics.Commands;
using MVVM_Basics.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace MVVM_Basics.ViewModels
{
internal class CustomerViewModel
{
/// <summary>
/// Initializes a new instance of the CustomerViewModel class
/// </summary>
//creating the constructor for the class
//setting a Name to a Customer instance
//initializing the UpdateCommand with command we created in the CustomerUpdateCOmmand class, the constructor takes in a ViewModel and since we are
//creating it here, we can reference CustomerViewModel by using the 'this' keyword.
public CustomerViewModel()
{
_Customer = new Customer("David"); //this is the hard coded value that I would like to be populated with a XML file
UpdateCommand = new CustomerUpdateCommand(this);
}
/// <summary>
/// Gets or Sets a Boolean value to indicating whether the Customer can be updated
/// </summary>
public bool CanUpdate
{
get
{
if(Customer == null)
{
return false;
}
return !String.IsNullOrWhiteSpace(Customer.Name);
}
}
//without adding logic to CanUpdate, the button that it is binding to will always be disabled because the default value for a boolean is false
//we added logic that only returned false if there was not a name in the text box.
/// <summary>
/// creates an instance of a Customer
/// </summary>
private Customer _Customer;
public Customer Customer
{
get{ return _Customer; }
}
/// <summary>
/// Gets the UpdateCommand for the ViewModel
/// </summary>
public ICommand UpdateCommand
{
get;
private set;
}
/// <summary>
/// Saves changes made to the Customer instance
/// </summary>
public void SaveChanges()
{
//because this is just a simple demo I am using the Debug property to display dialog. Normally this would save back to your actual dataset
Debug.Assert(false, String.Format("{0} was updated.", Customer.Name));
}
}
}
使用MVVM_Basics.command;
使用MVVM_Basics.Models;
使用制度;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Input;
命名空间MVVM_Basics.ViewModels
{
内部类CustomerViewModel
{
///
///初始化CustomServiceWModel类的新实例
///
//为类创建构造函数
//为客户实例设置名称
//使用我们在CustomerUpdateCOmmand类中创建的命令初始化UpdateCommand,构造函数接受一个ViewModel,因为我们
//在这里创建它,我们可以使用'this'关键字引用CustomerViewModel。
公共CustomerServiceModel()
{
_Customer=new Customer(“David”);//这是我希望用XML文件填充的硬编码值
UpdateCommand=新的CustomerUpdateCommand(此命令);
}
///
///获取或设置一个布尔值,以指示是否可以更新客户
///
公共图书馆更新
{
得到
{
如果(客户==null)
{
返回false;
}
return!String.IsNullOrWhiteSpace(Customer.Name);
}
}
//如果不向CanUpdate添加逻辑,它绑定到的按钮将始终被禁用,因为布尔值的默认值为false
//我们添加了只在文本框中没有名称时返回false的逻辑。
///
///创建客户的实例
///
私人客户(u客户),;
公众客户
{
获取{return\u Customer;}
}
///
///获取ViewModel的UpdateCommand
///
公共ICommand更新命令
{
得到;
私人设置;
}
///
///保存对客户实例所做的更改
///
公共void SaveChanges()
{
//因为这只是一个简单的演示,所以我使用Debug属性来显示对话框。通常这会保存回实际的数据集
Assert(false,String.Format(“{0}已更新。”,Customer.Name));
}
}
}
这里是风景
<Window x:Class="MVVM_Basics.Views.CustomerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MVVM_Basics.Views"
mc:Ignorable="d"
Title="Customer Update" Height="350" Width="520">
<Grid VerticalAlignment="Top" Margin="15">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Customer Name" />
<TextBox Grid.Column="1" Text="{Binding Customer.Name, UpdateSourceTrigger=PropertyChanged}" />
<Button Grid.Column="2" Command="{Binding UpdateCommand}" Content="Update" />
</Grid>
</Window>
任何帮助都将不胜感激,谢谢我开发了一个用于序列化的类,并为其提供了反序列化方法和序列化方法
namespace MVVM_Basics.Commands
{
//the following class is used to retrieve data that is in an XML document. The document is name Customer.xml and is located in the data folder.
//We are using the Deserialize feature to grab info needed from the XML doc and then data bind it to parts of a View through that View's ViewModel
public class Serializer
{
/// <summary>
/// populate a class with xml data
/// </summary>
/// <typeparam name="T">Object Type</typeparam>
/// <param name="input">xml data</param>
/// <returns>Object Type</returns>
public T Deserialize<T>(string input) where T : class
{
XmlSerializer ser = new XmlSerializer(typeof(T));
using (StringReader sr = new StringReader(input))
{
return (T)ser.Deserialize(sr);
}
}
/// <summary>
/// convert object to xml string
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ObjectToSerialize"></param>
/// <returns></returns>
public string Serialize<T>(T ObjectToSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(ObjectToSerialize.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, ObjectToSerialize);
return textWriter.ToString();
}
}
}
}
namespace MVVM\u Basics.Commands
{
//以下类用于检索XML文档中的数据。该文档名为Customer.XML,位于数据文件夹中。
//我们使用反序列化功能从XML文档中获取所需的信息,然后通过视图的ViewModel将其数据绑定到视图的某些部分
公共类序列化程序
{
///
///用xml数据填充类
///
///对象类型
///xml数据
///对象类型
公共T反序列化(字符串输入),其中T:class
{
XmlSerializer ser=新的XmlSerializer(typeof(T));
使用(StringReader sr=新StringReader(输入))
{
返回(T)序列反序列化(sr);
}
}
///
///将对象转换为xml字符串
///
///
///
///
公共字符串序列化(T ObjectToSerialize)
{
XmlSerializer XmlSerializer=新的XmlSerializer(ObjectToSerialize.GetType());
使用(StringWriter textWriter=new StringWriter())
{
序列化(textWriter,ObjectToSerialize);
返回textWriter.ToString();
}
}
}
}
然后在ViewModel中,我创建了一个客户变量和一个包含XML路径的变量。然后,我将反序列化的数据应用于创建我的客户对象的客户
//setting up some variable that will be use through this class
// the private read only is setting up a Customer data type that will have a customer object attached to it
private readonly Customer customer;
string path = Directory.GetCurrentDirectory() + @"\Customer.xml";
string xmlInputData = string.Empty;
public CustomerViewModel()
{
//we are defining that we are using the CustomerUpdateCommand with this ViewModel on construction of 'this' ViewModel
UpdateCommand = new CustomerUpdateCommand(this);
//the 'path' variable is the path to the XML file containing all Customer data, we first just check the file does exist, we then create
//an instance of the Serializer class and use that class on the XML file using the Deserialize method from the class. Then attached the data to an
//instance of a Customer object that we created a 'private readonly' variable for.
if (File.Exists(path))
{
xmlInputData = File.ReadAllText(path);
}
Serializer ser = new Serializer();
customer = ser.Deserialize<Customer>(xmlInputData);
}
//设置将通过此类使用的某些变量
//私有只读正在设置客户数据t