上一节我们学习如何在客户端进行同步数据校验,但在许多时候,我们需要把输入的数据与后台数据库中的数据进行校验,即把校验工作放到服务器端完成,然后把校验结果返回到客户端。
本篇文章主要演示:
1、如何利用WCF在服务器端进行数据校验。
2、如何制作一个异步等待数据校验的等待提示界面。
上一节我们学习如何在客户端进行同步数据校验,但在许多时候,我们需要把输入的数据与后台数据库中的数据进行校验,即把校验工作放到服务器端完成,然后把校验结果返回到客户端。
本篇文章主要演示:
1、如何利用WCF在服务器端进行数据校验。
2、如何制作一个异步等待数据校验的等待提示界面。
一、如何利用WCF在服务器端进行数据校验。 1、服务器端利用WCF完成数据校验功能
在SLApplicationDataTest.Web项目上"添加"--"新建项",新建一个"启用Silverlight的WCF服务",服务名命名为:SexWCF.svc,如下图:

编写SexWCF.svc.cs代码如下:
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;

namespace SLApplicationDataTest.Web


{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SexWCF

{
[OperationContract]

服务器端数据校验,返回结果为bool值#region 服务器端数据校验,返回结果为bool值
public bool SexValidation(string SexStr)

{
//延时处理,是为了后面我们在演示“等待校验提示窗口”时能有足够的时间看到提示窗口
System.Threading.Thread.Sleep(1000);



在此处添加服务器端的数据校验代码#region 在此处添加服务器端的数据校验代码
//此处,如果输入的性别是Male或Female则合法
return ("Male"==SexStr||"Female"==SexStr);
#endregion

}
#endregion



// 在此处添加更多操作并使用 [OperationContract] 标记它们
}
}

2、在客户端引用WCF数据校验服务
在SLApplicationDataTest项目上添加服务引用,如下图:

成功引入服务器端WCF服务后,我们需要修改Person类代码,在其中加入如下代码:
#region 性别输入校验程序:通过调用WCF服务来完成校验工作
private void ValidateSex(string SexStr)
{
SexWCFClient sexCs = new SexWCFClient();
sexCs.SexValidationCompleted += new EventHandler<SexValidationCompletedEventArgs>(sexCs_SexValidationCompleted);
sexCs.SexValidationAsync(SexStr, SexStr); //其中第二个SexStr为传入的UserState参数,将在sexCs_SexValidationCompleted中使用
}
public void sexCs_SexValidationCompleted(object sender, SexValidationCompletedEventArgs e)
{
if (!e.Result)
{
HtmlPage.Window.Alert(e.UserState.ToString() + " 无效,请重新输入!");//其中e.UserState是SexValidationAsync方法中的第二个传参
}
}
#endregion
这段代码使用了WCF数据校验服务来完成对SexStr的数据校验。
另外,我们需要修改Sex属性的Set段,如下:
public string Sex
{
get { return _sex; }
set
{
if (value == _sex) return;
_sex = value;
OnPropertyChanged("Sex");
ValidateSex(_sex); //调用WCF服务来进行数据校验
}
}
Person类全部代码如下:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel; //因为要用到INotifyPropertyChanged接口
using SLApplicationDataTest.SexServiceReference; //因为要使用WCF服务
using System.Windows.Browser; //因为要使用HtmlPage.Window.Alert


namespace SLApplicationDataTest


{
public class Person : INotifyPropertyChanged

{
private string _name;
private string _sex;
private int _age;
private string _address;


Constructors#region Constructors

public Person()
{ }

public Person(string NameStr, string SexStr, int AgeInt, string AddressStr)

{
this._name = NameStr;
this._sex = SexStr;
this._age = AgeInt;
this._address = AddressStr;
}
#endregion



Properties#region Properties

public string Name

{

get
{ return _name; }
set

{
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}

public string Sex

{

get
{ return _sex; }
set

{
if (value == _sex) return;
_sex = value;
OnPropertyChanged("Sex");
ValidateSex(_sex); //调用WCF服务来进行数据校验
}
}

public int Age

{

get
{ return _age; }
set

{
if (value == _age) return;

//如果输入的不是整数,则抛出异常
try

{
Convert.ToInt32(value);
}
catch(Exception ex)

{
throw new Exception(ex.ToString());
}
//如果输入的整数不在合理范围同,则也抛出异常

if (value < 0 || value > 200)

{
throw new Exception("Age must be between 0 and 200");
}


_age = value;
OnPropertyChanged("Age");
}
}

public string Address

{

get
{ return _address; }
set

{
if (value == _address) return;
_address = value;
OnPropertyChanged("Address");
}
}
#endregion


INotifyPropertyChanged 接口实现#region INotifyPropertyChanged 接口实现
public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string name)

{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#endregion



性别输入校验程序:通过调用WCF服务来完成校验工作#region 性别输入校验程序:通过调用WCF服务来完成校验工作
private void ValidateSex(string SexStr)

{
SexWCFClient sexCs = new SexWCFClient();
sexCs.SexValidationCompleted += new EventHandler<SexValidationCompletedEventArgs>(sexCs_SexValidationCompleted);
((Page)Application.Current.RootVisual).StartWait("请稍候,正在校验性别输入!");
sexCs.SexValidationAsync(SexStr, SexStr); //其中第二个SexStr为传入的UserState参数,将在sexCs_SexValidationCompleted中使用
}

public void sexCs_SexValidationCompleted(object sender, SexValidationCompletedEventArgs e)

{
((Page)Application.Current.RootVisual).EndWait(null);
if (!e.Result)

{
HtmlPage.Window.Alert(e.UserState.ToString() + " 无效,请重新输入!");//其中e.UserState是SexValidationAsync方法中的第二个传参
}
}

#endregion

}
}

上面,我们完成了如何利用WCF在服务器端进行数据校验,但这还不够,因为我们在后台进行数据校验时可能会处理一段时间,而如果等待时间过长,用户会认为程序卡住了,所以,我们需要给用户一个异步处理的提示信息,好让用户知道当前正在做什么,所以,下面我们来进一步完善异步校验工作,我们需要做一个提示界面。
二、如何制作一个异步等待数据校验的等待提示界面。
1、创建提示界面
在项目SLApplicationDataTest上添加一个新的Silverlight用户控件,如下图:

定义等待提示界面,PleaseWaitValidate.xaml如下:
<UserControl x:Class="SLApplicationDataTest.PleaseWaitValidate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="300" Height="150">
<Grid x:Name="LayoutRoot" >
<Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.75" Fill="WhiteSmoke" />
<Border CornerRadius="30" Background="CornflowerBlue" Width="300" Height="150">
<TextBlock Text="{Binding}" Padding="60" Foreground="Green" FontSize="18" TextWrapping="Wrap"/>
</Border>
</Grid>
</UserControl>
对此界面我们在后台编写两段代码(打开或关闭显示代码),PleaseWaitValidate.xaml.cs代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SLApplicationDataTest


{
public partial class PleaseWaitValidate : UserControl

{
public PleaseWaitValidate()

{
InitializeComponent();
}


打开显示#region 打开显示
public void StartWait()

{
this.Visibility = Visibility.Visible;
}
#endregion


关闭显示#region 关闭显示
public void StopWait()

{
this.Visibility = Visibility.Collapsed;
}
#endregion
}
}

2、引入提示界面。
在定义好提示等待界面后,我们需要要Silverlight主界面中引入和应用它。
引入方法如下,打开Page.xmal文件,加入下面代码:
xmlns:myscreen="clr-namespace:SLApplicationDataTest"
引入SLApplicationDataTest程序集,因为在此程序集中有我们定义的提示等待界面。
然后,在Page.xaml界面的DataGrid界面定义代码下加入:
<myscreen:PleaseWaitValidate x:Name="myWaitingSexValidateScreen" Visibility="Collapsed" Margin="8,2,2,2" Width="300" Height="150">
</myscreen:PleaseWaitValidate>
从而引入我们定义的等待提示界面控件。
至此Page.xaml全部代码如下:

Code
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="SLApplicationDataTest.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myscreen="clr-namespace:SLApplicationDataTest"
Width="600" Height="300">
<Canvas Width="600" Height="300" Background="Wheat">
<StackPanel Height="300" Width="600" Background="White">
<StackPanel Orientation="Horizontal">
<Button x:Name="addButton" Content="Add" Margin="10"/>
<Button x:Name="deleteButton" Content="Delete" Margin="10"/>
</StackPanel>
<data:DataGrid x:Name="dgPeople" AutoGenerateColumns="False" >
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<data:DataGridTextColumn Header="Sex" Binding="{Binding Sex}" />
<data:DataGridTemplateColumn Header="Age">
<data:DataGridTemplateColumn.CellTemplate >
<DataTemplate>
<TextBlock Text="{Binding Age}" ToolTipService.ToolTip="请输入0至200之间的整数!"></TextBlock>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Age , Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" BindingValidationError="TextBox_BindingValidationError"
ToolTipService.ToolTip="请输入0至200之间的整数!"></TextBox>
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>
<data:DataGridTextColumn Header="Address" Binding="{Binding Address}" />
</data:DataGrid.Columns>
</data:DataGrid>
</StackPanel>
<myscreen:PleaseWaitValidate x:Name="myWaitingSexValidateScreen" Visibility="Collapsed" Margin="8,2,2,2" Width="300" Height="150">
</myscreen:PleaseWaitValidate>
</Canvas>
</UserControl>
3、应用提示界面
编辑Page.xaml.cs代码,加入下面程序段:
#region 打开与关闭“等待校验窗口”
public void StartWait(string message)
{
this.myWaitingSexValidateScreen.DataContext = message;
this.myWaitingSexValidateScreen.StartWait();
}
public void EndWait(string message)
{
this.myWaitingSexValidateScreen.DataContext = message;
this.myWaitingSexValidateScreen.StopWait();
}
#endregion
编辑Person类定义代码,在数据校验代码段中加入下面代码:
((Page)Application.Current.RootVisual).StartWait("请稍候,正在校验性别输入!"); //打开等待提示界面,提示用户指定的提示信息
((Page)Application.Current.RootVisual).EndWait(null); //关闭等待提示界面
代码段如下:
#region 性别输入校验程序:通过调用WCF服务来完成校验工作
private void ValidateSex(string SexStr)
{
SexWCFClient sexCs = new SexWCFClient();
sexCs.SexValidationCompleted += new EventHandler<SexValidationCompletedEventArgs>(sexCs_SexValidationCompleted);
((Page)Application.Current.RootVisual).StartWait("请稍候,正在校验性别输入!"); //打开等待提示界面,提示用户指定的提示信息
sexCs.SexValidationAsync(SexStr, SexStr); //其中第二个SexStr为传入的UserState参数,将在sexCs_SexValidationCompleted中使用
}
public void sexCs_SexValidationCompleted(object sender, SexValidationCompletedEventArgs e)
{
((Page)Application.Current.RootVisual).EndWait(null); //关闭等待提示界面
if (!e.Result)
{
HtmlPage.Window.Alert(e.UserState.ToString() + " 无效,请重新输入!");//其中e.UserState是SexValidationAsync方法中的第二个传参
}
}
#endregion
Person.cs全部代码如下:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel; //因为要用到INotifyPropertyChanged接口
using SLApplicationDataTest.SexServiceReference; //因为要使用WCF服务
using System.Windows.Browser; //因为要使用HtmlPage.Window.Alert


namespace SLApplicationDataTest


{
public class Person : INotifyPropertyChanged

{
private string _name;
private string _sex;
private int _age;
private string _address;


Constructors#region Constructors

public Person()
{ }

public Person(string NameStr, string SexStr, int AgeInt, string AddressStr)

{
this._name = NameStr;
this._sex = SexStr;
this._age = AgeInt;
this._address = AddressStr;
}
#endregion



Properties#region Properties

public string Name

{

get
{ return _name; }
set

{
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}

public string Sex

{

get
{ return _sex; }
set

{
if (value == _sex) return;
_sex = value;
OnPropertyChanged("Sex");
ValidateSex(_sex); //调用WCF服务来进行数据校验
}
}

public int Age

{

get
{ return _age; }
set

{
if (value == _age) return;

//如果输入的不是整数,则抛出异常
try

{
Convert.ToInt32(value);
}
catch(Exception ex)

{
throw new Exception(ex.ToString());
}
//如果输入的整数不在合理范围同,则也抛出异常

if (value < 0 || value > 200)

{
throw new Exception("Age must be between 0 and 200");
}


_age = value;
OnPropertyChanged("Age");
}
}

public string Address

{

get
{ return _address; }
set

{
if (value == _address) return;
_address = value;
OnPropertyChanged("Address");
}
}
#endregion


INotifyPropertyChanged 接口实现#region INotifyPropertyChanged 接口实现
public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string name)

{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#endregion



性别输入校验程序:通过调用WCF服务来完成校验工作#region 性别输入校验程序:通过调用WCF服务来完成校验工作
private void ValidateSex(string SexStr)

{
SexWCFClient sexCs = new SexWCFClient();
sexCs.SexValidationCompleted += new EventHandler<SexValidationCompletedEventArgs>(sexCs_SexValidationCompleted);
((Page)Application.Current.RootVisual).StartWait("请稍候,正在校验性别输入!"); //打开等待提示界面,提示用户指定的提示信息
sexCs.SexValidationAsync(SexStr, SexStr); //其中第二个SexStr为传入的UserState参数,将在sexCs_SexValidationCompleted中使用
}

public void sexCs_SexValidationCompleted(object sender, SexValidationCompletedEventArgs e)

{
((Page)Application.Current.RootVisual).EndWait(null); //关闭等待提示界面

if (!e.Result)

{
HtmlPage.Window.Alert(e.UserState.ToString() + " 无效,请重新输入!");//其中e.UserState是SexValidationAsync方法中的第二个传参
}
}

#endregion

}
}

至此,我们完成了对等待提示界面的定义,引用和应用。运行程序效果如下:
异步校验时的等待提示界面如下图:

异步校验未通过时的提示信息

前往:Silverlight学习笔记清单 本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)