我打算用MVVM做一个wpf应用程序(它基于http://www.codeproject.com/KB/WPF/MVVMQuickTutorial.aspx )。
此应用程序将每月与webservice连接一次。
在webservice上我有合同
public class Student
{
public string Name {get; set;}
public int Score {get; set;}
public DateTime TimeAdded {get; set;}
public string Comment {get; set;}
}
在WPF应用程序中添加和删除学生将保存到xml文件。
所以在wpf应用程序学生会是这样的:
public class Student
{
public string Name {get; set;}
public int Score {get; set;}
public DateTime TimeAdded {get; set;}
public string Comment {get; set;}
public Student(string Name, int Score,
DateTime TimeAdded, string Comment) {
this.Name = Name;
this.Score = Score;
this.TimeAdded = TimeAdded;
this.Comment = Comment;
}
}
public class StudentsModel: ObservableCollection<Student>
{
private static object _threadLock = new Object();
private static StudentsModel current = null;
public static StudentsModel Current {
get {
lock (_threadLock)
if (current == null)
current = new StudentsModel();
return current;
}
}
private StudentsModel()
{
// Getting student s from xml
}
}
public void AddAStudent(String Name,
int Score, DateTime TimeAdded, string Comment) {
Student aNewStudent = new Student(Name, Score,
TimeAdded, Comment);
Add(aNewStudent);
}
}
如何连接这两个类?
最糟糕的想法我想是来自webservice的合同学生将在这个wpf应用程序中使用来从xml获取学生,其他应用程序集合中的学生将从数据库中获取。
我是设计模式的新手,所以对我来说很难:/
示例:我单击AddUser,在应用程序A中调用webservice方法将用户添加到数据库,在应用程序B中将用户添加到XML文件,并在应用程序中。 基类是webservice的合同。
下一个解释:
第一个应用程序使用webservice在数据库中保存数据。第二个应用程序永远不会在xmls中保存数据,每个perm月将此xmls发送到webservice并将其转换为学生的内容并将其保存在数据库中
答案 0 :(得分:7)
从您的问题中不清楚实际问题是什么。但是,我想我可以解决一些问题并向您展示解决问题的方法。
1)我在你的项目中看到的主要问题是你有Student
类的两个定义。您可以轻松地将它们合并为单个定义。 (我会告诉你如何...)
2)目前还不清楚您是希望WPF
客户端将数据保存到Data Source
(XML
?)还是Web Service
应该这样做。如果WPF
客户端应该保存Student
,那么Web Service
是什么?
3)ViewModel
类的任何地方都没有定义Student
,在这种情况下为Model
。
我创建了一个包含3个项目的示例。
1)WebService
- WCF服务项目
2)StudentLib
- 一个类库项目(其中定义了Student
类)
3)DesktopClient
- WPF应用项目
以下是源代码:
WebService.IStudentService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using StudentLib;
namespace WebService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IStudentService" in both code and config file together.
[ServiceContract]
public interface IStudentService
{
[OperationContract]
StudentLib.Student GetStudentById(Int32 id);
[OperationContract]
void AddStudent(StudentLib.Student student);
}
}
WebService.StudentService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using StudentLib;
namespace WebService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "StudentService" in code, svc and config file together.
public class StudentService : IStudentService
{
public StudentLib.Student GetStudentById(int id)
{
return new StudentLib.Student() { Name = "John Doe", Score = 80, TimeAdded = DateTime.Now, Comment = "Average" };
}
public void AddStudent(StudentLib.Student student)
{
// Code to add student
}
}
}
WebService's Web.Config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings />
<client />
<services>
<service name="WebService.StudentService" behaviorConfiguration="metaDataBehavior">
<endpoint address="basic" binding="basicHttpBinding" contract="WebService.IStudentService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metaDataBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
StudentLib.Student.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
namespace StudentLib
{
[DataContract]
public class Student
{
[DataMember]
public String Name { get; set; }
[DataMember]
public Int32 Score { get; set; }
[DataMember]
public DateTime TimeAdded { get; set; }
[DataMember]
public String Comment { get; set; }
}
}
DesktopClient.StudentViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DesktopClient
{
class StudentViewModel
{
protected StudentLib.Student Student { get; set; }
public StudentViewModel(StudentLib.Student student)
{
this.Student = student;
}
public String Name { get { return Student.Name; } }
public Int32 Score { get { return Student.Score; } }
public DateTime TimeAdded { get { return Student.TimeAdded; } }
public String Comment { get { return Student.Comment; } }
}
}
DesktopClient.MainWindow.xaml
<Window x:Class="DesktopClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="400"
Height="300"
Loaded="Window_Loaded">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Grid.Row="0">Name :</TextBlock>
<TextBlock Grid.Column="1"
Grid.Row="0"
Text="{Binding Name}"></TextBlock>
<TextBlock Grid.Column="0"
Grid.Row="1">Score :</TextBlock>
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="{Binding Score}"></TextBlock>
<TextBlock Grid.Column="0"
Grid.Row="2">Time Added :</TextBlock>
<TextBlock Grid.Column="1"
Grid.Row="2"
Text="{Binding TimeAdded}"></TextBlock>
<TextBlock Grid.Column="0"
Grid.Row="3">Comment :</TextBlock>
<TextBlock Grid.Column="1"
Grid.Row="3"
Text="{Binding Comment}"></TextBlock>
</Grid>
</Window>
DesktopClient.MainWindow.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DesktopClient.StudentService;
using StudentLib;
namespace DesktopClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
IStudentService client = new StudentServiceClient();
Student student = client.GetStudentById(1);
DataContext = new StudentViewModel(student);
client.AddStudent(new StudentLib.Student() { Name = "Jane Doe", Score = 70, TimeAdded = DateTime.Now, Comment = "Average" });
}
}
}
这里解决了上述所有问题:
1)Student
类在StudentLib
项目和WebService
项目引用的公共程序集(DesktopClient
)中定义。因此,在添加Service Reference
时,代码生成器会重用该类。
2)我建议所有与存储相关的操作都在Web Service
,而Client
应用只应使用Web Service
来存储数据。
3)使用StudentViewModel
类而不是Student
类来显示MainWindow
中的数据。
答案 1 :(得分:0)
您可以使用以下架构。
1)带有app.config的WPF应用程序(应用程序A和B),其中包含Web服务URL或XML文件路径
2)业务/数据层 为Web服务URL创建代理类,并创建您在帖子中提到的Student Model类。 修改Add方法以支持这两种功能。如果app.config具有webservice url(App A),则调用Webservice中的Add方法,如果appsetting具有XML文件路径(App B),则调用add to XML方法
答案 2 :(得分:0)
幸运的是,这些类已经“链接”了,至少在形式上是这样的:因为ViewModel只是一堆模型。
在MVVM模式中,您需要在ViewModel中处理数据绑定功能。这包括以下内容:
private StudentsModel() { ...
)应该使用所有Student实例加载自身。 (或者,您可以使用单独的Load()函数 - 如果您还有Save()方法,这似乎是最合乎逻辑的。)在这里,您可能会读取XML文件,使用XmlSerializer来deserialize将XML数据转换为学生集合(可能是List),然后使用base constructor(对于整个列表)或Add() method(一次一个,例如在循环中)将它们添加到自身。 您可能会注意到我在上面的解释中大部分都提到了XML序列化,但是为了制作具有类似功能的Web服务,您可以将“序列化XML并保存到文件中”等想法换成“将更改保存到数据库中” ”。模式是一样的,只是实际的行动(实施)是不同的。
简而言之,ViewModel就是您要实现所有加载和放置的东西的地方。处理内存中的数据并将其保存到文件,数据库或Web服务中。