2013年12月23日星期一

Silverlight使用WCF RIA SERVICE实现CUD

这篇文章主要是使用WCF RIA SERVICE实现对数据的新增,更新,删除(CUD)。 

一:查看数据详情


接上面文章,我们已经实现了数据的列表展示,列表展示的数据的详细是有限的,所以需要做一个表单显示某个数据的详情。 
1.我们需要用到Silverlight Tookit,可以从http://silverlight.codeplex.com/下载。Silverlight tookit提供了很多有用的控件,这里我们用到了DataForm控件,这个控件在程序集System.Windows.Controls.Data.DataForm.Toolkit.dll。复制这个DLL到HRApp项目的Libs文件夹,如果没有新建。 
2.打开EmployeeList.xaml文件,增加如下声明
xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
3.在EmployeeList页面的DataPager控件下面,加入下面的XAML。 
<dataForm:DataForm x:Name="dataForm1" Header="Employee Information" AutoGenerateFields="False" AutoEdit="False" AutoCommit="False" CurrentItem="{Binding SelectedItem, ElementName=dataGrid1}" Margin="0,12,0,0">
<dataForm:DataForm.EditTemplate>
<DataTemplate>
<StackPanel>
<dataForm:DataField Label="Employee ID">
<TextBox IsReadOnly="True"
Text="{Binding EmployeeID, Mode=OneWay}" />
</dataForm:DataField>
<dataForm:DataField Label="Login ID">
<TextBox Text="{Binding LoginID, Mode=TwoWay}" />
</dataForm:DataField>
<dataForm:DataField Label="Hire Date">
<TextBox Text="{Binding HireDate, Mode=TwoWay}" />
</dataForm:DataField>
<dataForm:DataField Label="Marital Status">
<TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" />
</dataForm:DataField>
<dataForm:DataField Label="Gender">
<TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />
</dataForm:DataField>
<dataForm:DataField Label="Vacation Hours">
<TextBox Text="{Binding VacationHours, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />
</dataForm:DataField>
<dataForm:DataField Label="Sick Leave Hours">
<TextBox Text="{Binding SickLeaveHours, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />
</dataForm:DataField>
<dataForm:DataField Label="Active">
<CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />
</dataForm:DataField>
</StackPanel>
</DataTemplate>
</dataForm:DataForm.EditTemplate>
</dataForm:DataForm>
4.运行程序,进入EmployeeList页面,在列表中选择一项,dataform会显示该条数据的详情。 
DataForm

二:更新数据

1.在新增Domain Service时 选中Enable Editing,选中后会自动生成CUD的方法。通过这些方法来更新数据。 
NewDSC 
2.新增一个编辑按钮到EmployeeList页面。放置这个Button在DataForm控件后面。 
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
<Button x:Name="submitButton" Width="75" Height="23" Content="Submit" Margin="4,0,0,0" Click="submitButton_Click"/>
</StackPanel>
3.处理按钮的单击事件。 
private void submitButton_Click(object sender, RoutedEventArgs e)
{
employeeDataSource.SubmitChanges();
}

4.运行程序进入EmployeeList列表,你可以通过点击那个铅笔,这时DataForm处于编辑模式。对数据更改后,单击OK,结束编辑模式。单击Submit按钮保存数据。 
5.有时候需要更新某个字段,需要在Domain Service新增一个自定义的方法。打开OrganizationService.cs文件,加入下面的自定义的方法 
public void ApproveSabbatical(Employee current)
{
// Start custom workflow here
this.ObjectContext.Employees.AttachAsModified(current);
current.CurrentFlag = false;
}

6.编译项目,然后打开EmployeeList.xaml,新增按钮ApprovalSabbatical。 
 <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
<Button x:Name="submitButton" Width="75" Height="23" Content="Submit" Margin="4,0,0,0" Click="submitButton_Click"/>
<Button x:Name="approveSabbatical" Width="115" Height="23" Content="Approve Sabbatical" Margin="4,0,0,0" Click="approveSabbatical_Click"/>
</StackPanel>

 private void approveSabbatical_Click(object sender, RoutedEventArgs e)
{
Employee luckyEmployee = (Employee)(dataGrid1.SelectedItem);
luckyEmployee.ApproveSabbatical();
employeeDataSource.SubmitChanges();
}

8.运行程序。 

三:数据验证

DataForm控件有显示数据验证错误的功能,如验证Email格式不正确等。 
ValidationError 
如何定义这些验证呢?在新增Domain Service Class的类的导航中,选中Generate associated classes for metadata。新增后会生成OrganizationService.metadata.cs,你可以在这里类中增加验证。 
genmetadate 
打开这个类,为下面的两个属性增加验证的特性 
[Required]
public string Gender { get; set; }
 
[Range(0, 70)]
public short VacationHours { get; set; }
运行程序查看效果: 
AttrValidateErr 

四:自定义数据验证

.NET自带的数据验证是很有限的,这时我们需要自己定义我们需要的数据验证。 
1.在HRApp.Web项目新增 一个Code File,名字是OrganizationService.shared.cs。每当我们以.share.cs结尾命名的文件名,都会在Generated_Code生成。我们在这个文件加入下面的的代码: 
using System;
using System.ComponentModel.DataAnnotations;
 
namespace HRApp.Web
{
 public static class GenderValidator
 {
 public static ValidationResult IsGenderValid(string gender, ValidationContext context)
 {
 if (string.Compare(gender,"M", StringComparison.CurrentCultureIgnoreCase)==0 ||
 string.Compare(gender,"F",StringComparison.CurrentCultureIgnoreCase)==0)
 return ValidationResult.Success;
 else
 return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] { "Gender" });
 }
 }
}
打开OrganizationService.metadata.cs,在Gender属性加上上面的特性: 
[CustomValidation(typeof(HRApp.Web.GenderValidator), "IsGenderValid")]
[Required]
public string Gender { get; set; }
运行程序查看效果: 
customvaldationError  
还有一种自定义验证的方法是使用特性。数据验证的特性都是集成于ValidationAttribute的。通过重写IsValid方法来实现自定义验证。同样我们新增一个以shared.cs结尾的类文件。如下面代码实现如上面代码同样的功能: 
using System;
using System.ComponentModel.DataAnnotations;
 
namespace HRApp.Web
{
 public class GenderAttribute : ValidationAttribute
 {
 public GenderAttribute()
 {
 this.ErrorMessage = "The Gender field only has two valid values 'M'/'F'";
 }
 
 protected override ValidationResult IsValid(object value, ValidationContext validationContext)
 {
 if (value is string)
 {
 if (string.Compare(value.ToString(), "M", StringComparison.CurrentCultureIgnoreCase) == 0 ||
 string.Compare(value.ToString(), "F", StringComparison.CurrentCultureIgnoreCase) == 0)
 return ValidationResult.Success;
 else
 return new ValidationResult(ErrorMessage, new string[] { "Gender" });
 }
 else
 return new ValidationResult(ErrorMessage, new string[] { "Gender" });
 }
 }
}

五:新增

新增一个界面,用于录入员工信息。在HRApp项目,我们新增一个Silverlight Child Window 页面,名字是EmployeeRegistrationWindow.xaml。 
Addsilchildwin 
引用下面的命名空间 
using HRApp.Web;
增加下面的属性: 
public Employee NewEmployee { get; set; }
打开EmployeeRegistrationWindow.xaml文件,我们隐藏这个窗体的关闭按钮,需要为此窗体加入下面的属性: 
<controls:ChildWindow x:Class="HRApp.EmployeeRegistrationWindow"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
 xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
 Width="400" Height="300" 
 Title="EmployeeRegistrationWindow"
 HasCloseButton="False">
</controls:ChildWindow>
这里需要用到DataForm控件,所以在XAML里面声明下这个控件所在的命名空间: 
xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
增加DataForm控件到EmployeeRegistrationWindow.xaml。 
<dataForm:DataForm x:Name="addEmployeeDataForm" AutoGenerateFields="False" AutoCommit="True" AutoEdit="True" CommandButtonsVisibility="None">
 <dataForm:DataForm.EditTemplate>
 <DataTemplate>
 <StackPanel>
 <dataForm:DataField Label="Login ID">
 <TextBox Text="{Binding LoginID, Mode=TwoWay}" />
 </dataForm:DataField>
 <dataForm:DataField Label="National ID">
 <TextBox Text="{Binding NationalIDNumber, Mode=TwoWay}" />
 </dataForm:DataField>
 <dataForm:DataField Label="Title">
 <TextBox Text="{Binding Title, Mode=TwoWay}" />
 </dataForm:DataField>
 <dataForm:DataField Label="Marital Status">
 <TextBox Text="{Binding MaritalStatus, Mode=TwoWay}" />
 </dataForm:DataField>
 <dataForm:DataField Label="Gender">
 <TextBox Text="{Binding Gender, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />
 </dataForm:DataField>
 <dataForm:DataField Label="Salaried">
 <CheckBox IsChecked="{Binding SalariedFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />
 </dataForm:DataField>
 <dataForm:DataField Label="Active">
 <CheckBox IsChecked="{Binding CurrentFlag, Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True }" />
 </dataForm:DataField>
 </StackPanel>
 </DataTemplate>
 </dataForm:DataForm.EditTemplate>
</dataForm:DataForm>
打开EmployeeRegistrationWindow.xaml.cs文件,加入下面的代码: 

public partial class EmployeeRegistrationWindow : ChildWindow
{
 public EmployeeRegistrationWindow()
 {
 InitializeComponent();
 NewEmployee = new Employee();
 addEmployeeDataForm.CurrentItem = NewEmployee;
 addEmployeeDataForm.BeginEdit(); 
 }
 
 private void OKButton_Click(object sender, RoutedEventArgs e)
 {
 addEmployeeDataForm.CommitEdit();
 this.DialogResult = true;
 }
 
 private void CancelButton_Click(object sender, RoutedEventArgs e)
 {
 NewEmployee = null;
 addEmployeeDataForm.CancelEdit();
 this.DialogResult = false;
 }
 
 public Employee NewEmployee { get; set; }
}
打开EmployeeList.xaml页面,增加一个Add按钮,放在DataPager和DataForm控件之间: 
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
 <Button x:Name="addNewEmployee" Width="90" Height="23" Content="Add Employee" Margin="4,0,0,0" Click="addNewEmployee_Click"/>
</StackPanel>
实现按钮的单击事件,同时为新增的窗体增加关闭的事件: 
private void addNewEmployee_Click(object sender, RoutedEventArgs e)
{
 EmployeeRegistrationWindow addEmp = new EmployeeRegistrationWindow();
 addEmp.Closed += new EventHandler(addEmp_Closed);
 addEmp.Show();
}
 
void addEmp_Closed(object sender, EventArgs e)
{
 EmployeeRegistrationWindow emp = (EmployeeRegistrationWindow)sender;
 if (emp.NewEmployee != null)
 {
 OrganizationContext _OrganizationContext = (OrganizationContext)(employeeDataSource.DomainContext);
 _OrganizationContext.Employees.Add(emp.NewEmployee);
 employeeDataSource.SubmitChanges();
 }
}

新增的时候会调用OrganizationService.cs中的InsertEmployee方法。我们可以自定义这个方法。 
public void InsertEmployee(Employee employee)
{
 // Modify the employee data to meet the database constraints.
 employee.HireDate = DateTime.Now;
 employee.ModifiedDate = DateTime.Now;
 employee.VacationHours = 0;
 employee.SickLeaveHours = 0;
 employee.rowguid = Guid.NewGuid();
 employee.ContactID = 1001;
 employee.BirthDate = new DateTime(1967, 3, 18);
 
 if ((employee.EntityState != EntityState.Detached))
 {
 this.ObjectContext.ObjectStateManager.ChangeObjectState(employee, EntityState.Added);
 }
 else
 {
 this.ObjectContext.Employees.AddObject(employee);
 }
}
运行程序。 


http://www.cnblogs.com/sonce/archive/2011/02/26/1965896.html