Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF MVVM结构中数据源的XML_C#_Wpf_Mvvm - Fatal编程技术网

C# WPF MVVM结构中数据源的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

在设计WPF应用程序时,我正在学习MVVM模式。到目前为止,我正在学习一个非常好的教程,但是他们在ViewModel的构造函数中填充了模型数据。在本教程中提到,在现实世界中,数据将从数据库或XML文件中提供。我真的很想知道如何使用XML文件填充模型数据,因为我讨厌代码中有硬编码的值

这是我的模型

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