WCF+EF 实战四:UI层MVP模式处理
在本系列的第一篇中,我们曾经描述了本系统的整个实现结构,可以查看第一篇。
在客户端的实现我们将采用MVP模式来实现,就是将客户端再分为二层,UI及presenter,
UI主要是定义界面的元素及响应客户的操作。Presenter主要是对UI层响应客户端操作的业务处理。关于MVP的一些知识,如果不太清楚可以查看http://blog.csdn.net/greystar/archive/2008/12/01/3418307.aspx
MVP中的Model我们不需要实现了,因为WCF服务将会给我们提供相应的model.
下面我们新建一个类库Demo. Presentation,同时添加上次创建的WCF的服务的引用。(先要运行Demo.同时注意要点下图的高级,将返回的集合类型设为泛型List。
由于我们的UI业务相当的简单,就是对Employee对象进行增删改查。因此首先我们定义
MVP中的View接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demo.Presentation.WCFService;
namespace Demo.Presentation
{
public delegate void VoidEventHandler();
public interface IUserView
{
/// <summary>
/// 当前员工
/// </summary>
Employee CurrentEmployee { get; set; }
/// <summary>
/// 员工列表
/// </summary>
List<Employee> Users { set; }
/// <summary>
/// 新增事件
/// </summary>
event VoidEventHandler OnAddNewEmp;
/// <summary>
/// 删除
/// </summary>
event VoidEventHandler OnDeleteEmp;
/// <summary>
/// 更新
/// </summary>
event VoidEventHandler OnUpdateEmp;
/// <summary>
/// 初始事件
/// </summary>
event VoidEventHandler PrepareView;
}
/// <summary>
/// 定义员工业务的操作
/// </summary>
public interface IUserPresenter
{
void AddNewUser();
void DeleteUser();
List<Employee> GetUsers();
void UpdateUser();
}
}
Presenter的真正实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demo.Presentation.WCFService;
namespace Demo.Presentation
{
public class UserPresenter:IUserPresenter
{
private IUserView view = null;
public UserPresenter(IUserView View)
{
view = View;
view.PrepareView += new VoidEventHandler(view_PrepareView);
view.OnAddNewEmp += new VoidEventHandler(AddNewUser);
view.OnDeleteEmp += new VoidEventHandler(DeleteUser);
view.OnUpdateEmp += new VoidEventHandler(UpdateUser);
}
void view_PrepareView()
{
view.Users = GetUsers();
}
#region IUserPresenter 成员
public void AddNewUser()
{
using (EmployeeServiceClient client = new EmployeeServiceClient())
{
view.CurrentEmployee= client.Add(view.CurrentEmployee);
}
}
public void DeleteUser()
{
using (EmployeeServiceClient client = new EmployeeServiceClient())
{
client.Delete(view.CurrentEmployee);
}
}
public List<Employee> GetUsers()
{
using (EmployeeServiceClient client = new EmployeeServiceClient())
{
return client.GetEmployees();
}
}
public void UpdateUser()
{
using (EmployeeServiceClient client = new EmployeeServiceClient())
{
client.Update(view.CurrentEmployee);
}
}
#endregion
}
}
}
现在我们来实现客户端的UI。当然UI要响应用户的操作,会调用到Demo. Presentation。但其本身不会直接处理任何数据。
添加一个window类库 Demo.UI
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Demo.Presentation.WCFService;
using Demo.Presentation;
namespace Demo.UI
{
public partial class Form1 : Form,IUserView
{
IUserPresenter presenter = null;
BindingSource bs = null;
public Form1()
{
InitializeComponent();
presenter = new UserPresenter(this);
this.PrepareView();//初始化视图
}
#region IUserView 成员
Employee _currentEmployee = null;
public Employee CurrentEmployee
{
get
{
return _currentEmployee;
}
set
{
_currentEmployee = value;
}
}
public List<Employee> Users
{
set {
bs = new BindingSource();
bs.DataSource = value;
this.dataGridView1.DataSource = bs;
}
}
public event VoidEventHandler OnAddNewEmp;
public event VoidEventHandler OnDeleteEmp;
public event VoidEventHandler OnUpdateEmp;
public event VoidEventHandler PrepareView;
#endregion
private void cmdDelete_Click(object sender, EventArgs e)
{
if (SelectedEmployee != null)
{//可以先确认一下是否删除
OnDeleteEmp();
bs.Remove(_currentEmployee);//完成后将对象从界面中移除
}
}
private void cmdRefresh_Click(object sender, EventArgs e)
{
PrepareView();
}
private void cmdAdd_Click(object sender, EventArgs e)
{
_currentEmployee = new Employee();
//将此对象传到其他窗口,完成编辑
OnAddNewEmp();
bs.Add(_currentEmployee); //新增完成后_currentEmployee对象就是从服务器传回来的对象,有状态,下次更新就不会有问题。
//同时加入到界面中
}
private void cmdUpdate_Click(object sender, EventArgs e)
{
if (SelectedEmployee != null)
{
//此处可以将CurrentUser对象传给其他的窗体进行编辑。
//省略
OnUpdateEmp();
}
}
/// <summary>
/// 判断网格是否有选择的
/// </summary>
Employee SelectedEmployee
{
get
{
if (dataGridView1.SelectedRows.Count == 0)
return null;
_currentEmployee = this.dataGridView1.SelectedRows[0].DataBoundItem as Employee;
return _currentEmployee;
}
}
}
}
我们的界面实现了IUserView接口,在界面里只处理最基本的一些操作,而数据访问的实现实际是是由IUserPresenter来完成的。当有用户操作时,只需引发一些相关的事件。如果要进行UI的移植,那么相应的工作量将会大大的减少。
同时将刚才在Demo.Presentation里的app.config复制到Demo.UI里,此时你可以运行程序了。当然你要记得先运行Demo.WCFHost,再运行Demo.UI
仅仅是一个DEMO相对来说比较的简单,实际在使用EF时真的很难用。很多最终的SQL语句我发觉都不是自己想要的那种简单的。搞得太复杂了。网上的资料也比较少,同时也遇到了很多的难题。以后我会讲一下EF中遇到的问题。