本文将示例如何运用前篇所写知识来建立一个用户自定义的登录控件。此控件界面非常简单,主要涉及的知识点是:
如何创建用户控件(包括对此控件的自定义事件和属性的编写,此处我们将创建一个名为LoginBox和LoginButton两个用户控件,其中,LoginBox控件内含LoginButton控件,LoginButton控件继承自Button控件。LoginBox和LoginButton两个控件之间将通过自定义事件和自定义属性进行交互) 如何创建一个用C#编写的后台代码类(UserDetail.cs),并在xaml文件中操作它(实例化它的一个类对象并把它和上面创建的用户LoginBox控件的自定义属性(名为UserName的属性)进行数据绑定,并在控件加载时自动显示出来)
本文将示例如何运用前篇所写知识来建立一个用户自定义的登录控件。此控件界面非常简单,主要涉及的知识点是:
如何创建用户控件(包括对此控件的自定义事件和属性的编写,此处我们将创建一个名为LoginBox和LoginButton两个用户控件,其中,LoginBox控件内含LoginButton控件,LoginButton控件继承自Button控件。LoginBox和LoginButton两个控件之间将通过自定义事件和自定义属性进行交互) 如何创建一个用C#编写的后台代码类(UserDetail.cs),并在xaml文件中操作它(实例化它的一个类对象并把它和上面创建的用户LoginBox控件的自定义属性(名为UserName的属性)进行数据绑定,并在控件加载时自动显示出来)
下面,进入我们的具体操作:
首先,我们打开VS2008,选择新建项目,项目名命名为LoginCtrlWeb,这是我们新建的解决方案,其下有两个项目,分别名为 LoginCtrlWeb 和 LoginCtrlWeb .Web
一、创建LoginButton控件
在LoginCtrlWeb项目下添加一个新建类,名称为 LoginButton.cs,此类继承自Button类,我们将在此类中自定义一个名为OnMyBtnClick的事件。
我们知道,自定义事件通常涉及到事件的发起方和事件的接收方,通常有4个具体步骤:
(1)、在事件发起方中定义一个事件(首先声明一个与事件相关联的委托类型 A,然后声明事件B,并把它和我们前面声明的代理类A关联起来)
(2)、在事件发起方中触发上面定义的事件B
(3)、在事件接收方定义上述事件的事件处理程序
(4)、事件接收方向事件发起方订阅一个事件在此代码中,
注意在.NET Framework中,涉及事件的各元素的命名规则如下(例如事件名为 EventName):
事件传递参数 EventName + EventArgs
事件涉及的委托类 EventName + EventHandler (object sender,EventNameEventArgs e)
事件名 OnEventName
在引发事件的类中提供一个受保护的虚方法: On+EventName,防止可能存在的线程同步问题
protect virtual void OnEventName(EventNameEventArgs e)
{
if(EventName !=null)
{
EventName(this.e);
}
}
作为自定义事件OnMyBtnClick的发起方LoginButton,我们需要在它这里完成的工作包括:
定义一个事件OnMyBtnClick和 定义一个触发上述事件的方法MyBtnClick,此外,我们还自定义了一个名为OnMyBtnClickEventArgs的参数类用于事件传参,此类继承自EventArgs类。
具体代码如下:
Code
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;
namespace LoginCtrlWeb
{
public class OnMyBtnClickEventArgs : EventArgs
{
//定义UserNameEventArgs类,将用于自定义事件处理函数,它的命名规则是: EventName+EventArgs
private readonly string _username;
private readonly string _password;
public OnMyBtnClickEventArgs(string username, string password)
{
_username = username;
_password = password;
}
public string userName
{
get { return _username; }
}
public string passWord
{
get { return _password; }
}
}
public class LoginButton:Button //用户自定义的LoginButton类
{
//首先声明一个与事件相关联的委托类型,它必须使用void作为返回值,同时它必须接收两个传入参数,一律命名为 sender 和 e
public delegate void OnMyBtnClickEventHandler(object sender, OnMyBtnClickEventArgs e); //delegate的命名规则: EventName+EventHandler
//然后声明了事件OnMyBtnClick,并把它和我们上面声明的代理 OnMyBtnClickEventHandler 关联起来
public event OnMyBtnClickEventHandler OnMyBtnClick; //事件的命名规则:
//声明一个受保护的虚方法
protected virtual void OnOnMyBtnClick(OnMyBtnClickEventArgs e)
{
OnMyBtnClickEventHandler handler = OnMyBtnClick; //定义一个临时变量handler,这样操作是防止可能存在的线程同步问题
if (handler!=null)
{
handler(this, e);
}
}
//定义一个触发事件的方法
public void MyBtnClick(string userName, string passWord)
{
//if (OnMyBtnClick != null)
//{
// OnMyBtnClick(this, new OnMyBtnClickEventArgs(userName, passWord)); //触发事件,其本质就是触发一个委托链
//}
OnOnMyBtnClick(new OnMyBtnClickEventArgs(userName, passWord)); //调用上面定义的虚方法OnOnMyBtnClick来触发事件
}
}
}
二、创建loginBox控件。
接下来,我们将创建loginBox控件,在此控件中,我们要用到上面创建的loginButton控件,步骤如下:
1、在LoginCtrlWeb项目下添加一个新建项(项目类型是:Silverlight用户控件),此新建项命名为LoginBox.xaml,先创建它的界面:
Code
<UserControl x:Class="LoginCtrlWeb.LoginBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:LoginCtrlWeb">
<Grid x:Name="LayoutRoot" Background="Chartreuse" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="用户名" Margin="10" Grid.Row="0" Grid.Column="0" Loaded="TextBlock_Loaded"></TextBlock>
<TextBox x:Name="txtUserName" Margin="10" Grid.Row="0" Grid.Column="1" Width="200"></TextBox>
<TextBlock Text="密码" Margin="10" Grid.Row="1" Grid.Column="0"></TextBlock>
<TextBox x:Name="txtUserPwd" Margin="10" Grid.Row="1" Grid.Column="1" Width="200"></TextBox>
<custom:LoginButton x:Name="btnLoginOK" Grid.Row="2" Grid.Column="1" Height="50" Width="100" Content="登录" Margin="100,0,0,0" Click="btnLoginOK_Click" />
<TextBlock x:Name="tbLoginMsg" Grid.Row="3" Grid.ColumnSpan="2" Width="Auto" Text="登录结果提示信息栏"></TextBlock>
</Grid>
</UserControl>
由于要用到控件loginButton,所以,我们需要在xaml文件头引用
xmlns:custom="clr-namespace:LoginCtrlWeb"
2、LoginBox.xaml.cs后台代码编写
包括两方面的任务,一是为loginBox自定义控件添加一个新属性UserName,二是为LoginBox控件添加loginButton控件所传递过来的OnMyBtnClick事件的事件处理程序
首先,我们添加新属性,代码如下:
Code
public static DependencyProperty UserNameProperty =
DependencyProperty.Register("UserName", typeof(string), typeof(LoginBox), null); //定义并注册一个Dependency类型的属性,用于实现在前台的动态绑定
public string UserName
{
get
{
return((string)base.GetValue(UserNameProperty));
}
set
{
base.SetValue(UserNameProperty,value);
}
}
然后,我们添加OnMyBtnClick事件的事件处理程序getLoginUserInfo,此程序就是事件委托类的一个具体实例,代码如下:
Code
private void getLoginUserInfo(object sender, OnMyBtnClickEventArgs e)
{
//声明一个当接收到事件产生信息时,在接收方对事件进行处理的程序段
if(ChekPassword(e.userName,e.passWord))
{
//在此处加入如果用户名和密码检查通过,则需要做的下一步处理
//我们在此处只是在输入框下面的textBlock上显示信息"用户正常登录"
this.tbLoginMsg.Text = "用户 " + e.userName + "正常登录本系统";
}
}
其中包括另一个子程序 ChekPassword,用于对用户名和密码进行核对,我们在此处假设核对通过并返回true代码如下
Code
//检查用户名和密码是否匹配,如果匹配则返回true,否则返回false;
bool ChekPassword(string userName, string passWord)
{
//在此处添加检查用户名和密码的代码段,如果用户名和密码匹配则返回true
return (true);
}
接下来,我们需要订阅OnMyBtnClick 事件,并触发事件,此段代码我们放在loginButton控件的Click事件处理代码中.
Code
private void btnLoginOK_Click(object sender, RoutedEventArgs e)
{
btnLoginOK.OnMyBtnClick += new LoginButton.OnMyBtnClickEventHandler(getLoginUserInfo); //向事件发行方订阅一个事件
this.btnLoginOK.MyBtnClick(this.txtUserName.Text, this.txtUserPwd.Text); //触发一个事件
}
LoginBox.xaml.cs完整程序代码如下:
Code
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 LoginCtrlWeb
{
public partial class LoginBox : UserControl
{
public static DependencyProperty UserNameProperty =
DependencyProperty.Register("UserName", typeof(string), typeof(LoginBox), null); //定义并注册一个Dependency类型的属性
public string UserName
{
get
{
return((string)base.GetValue(UserNameProperty));
}
set
{
base.SetValue(UserNameProperty,value);
}
}
public LoginBox()
{
InitializeComponent();
}
//检查用户名和密码是否匹配,如果匹配则返回true,否则返回false;
bool ChekPassword(string userName, string passWord)
{
//在此处添加检查用户名和密码的代码段,如果用户名和密码匹配则返回true
return (true);
}
private void btnLoginOK_Click(object sender, RoutedEventArgs e)
{
btnLoginOK.OnMyBtnClick += new LoginButton.OnMyBtnClickEventHandler(getLoginUserInfo); //向事件发行方订阅一个事件
this.btnLoginOK.MyBtnClick(this.txtUserName.Text, this.txtUserPwd.Text); //触发一个事件
}
private void getLoginUserInfo(object sender, OnMyBtnClickEventArgs e)
{
//声明一个当接收到事件产生信息时,在接收方对事件进行处理的程序段
if(ChekPassword(e.userName,e.passWord))
{
//在此处加入如果用户名和密码检查通过,则需要做的下一步处理
//我们在此处只是在输入框下面的textBlock上显示信息"用户正常登录"
this.tbLoginMsg.Text = "用户 " + e.userName + "正常登录本系统";
}
}
private void TextBlock_Loaded(object sender, RoutedEventArgs e)
{
this.txtUserName.Text = UserName;
}
}
}
三、在Page.xaml文件中运用我们创建的自定义控件loginBox.
此处我们需要做如下工作:
1、新建一个UserDetails类,代码如下:
Code
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;
namespace LoginCtrlWeb
{
public class UserDetails
{
public string UserName { get; set; }
}
}
2、在Page.xaml文件中初始化一个UserDetails类的实例,代码如下 :
<UserControl.Resources>
<custom:UserDetails UserName="Jack" x:Key="myUserDetials"/>
</UserControl.Resources>
当然,我们需要在Page.xaml文件头部加入引用
xmlns:custom="clr-namespace:LoginCtrlWeb"
这样,我们才能真正在xaml文件中操作此类
3、在Page.xaml文件中加入我们的自定义控件loginBox
Code
<custom:LoginBox x:Name="MyLoginBox"
DataContext="{StaticResource myUserDetials}"
UserName="{Binding UserName}" Margin="50">
</custom:LoginBox>
从代码中我们可以看到,当我们加入我们的自定义控件loginBox时,我们对此控件的自定义属性UserName进行了初始化赋值,赋值方式就是把它和我们定义的UserDetails类的一个实例进行绑定,而对UserDetails类所进行的初始化操作是在xmal文件中完成的。
Page.xaml完整代码如下:
Code
<UserControl x:Class="LoginCtrlWeb.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:LoginCtrlWeb"
Width="400" Height="250">
<UserControl.Resources>
<custom:UserDetails UserName="Jack" x:Key="myUserDetials"/>
</UserControl.Resources>
<StackPanel x:Name="layoutRoot" Background="Cornsilk">
<custom:LoginBox x:Name="MyLoginBox"
DataContext="{StaticResource myUserDetials}"
UserName="{Binding UserName}" Margin="50">
</custom:LoginBox>
</StackPanel>
</UserControl>
最后,按F5测试,可看到loginBox控件在加载时就已经绑定了用户名 Jack,点击自定义的登录按钮后,在下面将显示"用户 Jack 正常登录本系统"提示信息.
说明:本文只重在知识点的展示,即通过本例加深对上述知识点的理解,实际操作并非如此,比如,我们对Button控件的Click事件又另定义了一个OnMyBtnClick自定义事件,并把它放入到Click事件的处理程序中进行触发,在此处实际就是多此一举,在我们只是通过这种操作来进行说明,实际上你可以用到本文的相关知识,加入其它事件的自定义,而不仅是Click事件的定义.
前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)