Asp.net用户控件和委托事件

在Asp.net系统制作过程中,门户类型的网站,我们可以用DIV+CSS+JS+Ajax全部搞定,但是一旦遇到界面元素比较复杂的时候,还是UserControl比较方便一些,各种封装,各种处理,然后拖到主页面,就好了。本文主要讲解如何在UserControl和WebForm页面中利用委托事件传值。本文仅提供一种思路,如果有更好的方案,还敬请赐教。

首先,我们设计一个简单的UserControl页面(实际应用中,我们可以按照业务逻辑,做的复杂一些),请看下图:

然后在Default.aspx页面中,我们只需要显示出从UserControl返回过来的值即可。

在这里,我相信很多人都选择利用Session或者是Application或者是Cache等等,这些确实也都可以,不过我这次利用Delegate 和 Event来实现,好处有几点:首先传过来的值不会莫名其妙的丢失(Session会过期,Cache的东西也会过期,或者是丢失);其次就是代码更好控制,如果UserControl中新加一些其他控件传值过来,不用new session或者是cache等,直接放到事件中,抛向接收页面就行;再者就是由于有事件回调函数,不用再另设Flag来判断UserControl是不是执行完毕等等。

下面是UserControl前台HTML内容,不做讲解:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyUC.ascx.cs" Inherits="DelegateWeb.MyUC" %>
<div style="border-bottom:1px solid wheat;width:600px;height:100px; line-height:100px;">
请选择省份:
<asp:DropDownList ID="ddlBind" runat="server" Height="22px"  Width="200px">
<asp:ListItem Value="0">请选择</asp:ListItem>
<asp:ListItem Value="1">上海市</asp:ListItem>
<asp:ListItem Value="2">北京市</asp:ListItem>
<asp:ListItem Value="3">广州市</asp:ListItem>
<asp:ListItem Value="4">深圳市</asp:ListItem>
<asp:ListItem Value="5">河南省</asp:ListItem>
<asp:ListItem Value="6">山东省</asp:ListItem>
</asp:DropDownList>
&nbsp;<asp:TextBox ID="txtKeyWords" runat="server"></asp:TextBox>
&nbsp;<asp:Button ID="btnQuery" runat="server" Text="查询内容"  onclick="btnQuery_Click" />
</div>
View Code

下面是UserControl后台代码内容:

using System;
using System.Threading;

namespace DelegateWeb
{
    public delegate void CalculateDelegate(string ddlValue, string keyWords); //定义全局委托
    public partial class MyUC : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        public event CalculateDelegate CalculateEvent; //定义事件
        protected void btnQuery_Click(object sender, EventArgs e)
        {
            //睡眠5s,模拟数据执行操作
            Thread.Sleep(5000);
            string ddlSelectedTextValue = ddlBind.SelectedItem.Text + "|" + ddlBind.SelectedItem.Value;
            string keyWords = txtKeyWords.Text;
             //如果该事件已经被订阅,则抛出事件,
            // 这里也预示着函数已经执行完毕,开始抛出执行后的结果了
            if (CalculateEvent != null)
                CalculateEvent(ddlSelectedTextValue, keyWords);
        }
    }
}
View Code

这里的代码很简单,其实就是利用委托事件,当操作完成后,将执行结果利用事件抛出去。
既然我把执行结果抛出去了,那么该由谁来接呢?毋庸置疑,当然是放置它的主页面来接收了。我们拖动这个UserControl到主页面中,则主页面中会通过

<%@ Register src="MyUC.ascx" tagname="MyUC" tagprefix="uc1" %>

来注册UserControl

在主页面代码中,我们需要接住刚刚抛出的事件:

using System;
using System.Web;

namespace DelegateWeb
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            MyUC1.CalculateEvent += (selectedItem, keyWords) =>
            {
                lblResult.Text =  selectedItem +"  "+ keyWords;
            };
            //事件的注册都要放到IsPostBack判断外面,否则会出现丢失的情况
            if (!IsPostBack)
            {
            }
        }
    }
}
View Code

这个我就不多说了,+=号操作就代表注册事件,以便于进行回调操作。
如果只是说到这里,那么在Ajax大行其道的今天,点击按钮就刷新页面的做法并不会受到很多人的欢迎。这里我就来让操作Ajax话。

首先拖动ScriptManager到主页面中,然后拖动UpdatePanel到主页面中,整个首页布局如下面的样子即可:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DelegateWeb.Default" %>
<%@ Register src="MyUC.ascx" tagname="MyUC" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        body{font-size:12px;}
        #MyUC1_ddlBind{border:1px solid wheat;}
        #MyUC1_txtKeyWords{border:1px solid wheat;}
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <uc1:MyUC ID="MyUC1" runat="server" />
        <p>
            从UserControl接收的内容为:<asp:Label ID="lblResult" runat="server" Text=""></asp:Label>
        </p>
        </ContentTemplate>
    </asp:UpdatePanel>
    </form>
</body>
</html>
View Code

然后点击按钮,5秒后,页面输出了结果,而且完全实现了无刷新页面局部调用。
显示结果如下:

 

 做到这里,需要提示下,由于C#提供了Action委托,所以我们现在不需要声明Delegate委托,直接利用Action,也能实现效果:

 public event Action<string, string> CalculateEvent;

 这篇文章可能过于简单了,但是提供了一种思路。我很想通过这篇文章和大家讨论下Asp.net中的事件传递等方面的内容,包括怎么设计等等,以期能够抛砖引玉。

已标记关键词 清除标记
Form1类里的代码 public Class1 cla; private void button1_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.Show(); cla.run1(); } private void Form1_Load(object sender, EventArgs e) { cla = new Class1(this,LK); } void LK() { button1.Text = "abc"; } Form2类里的代码 public Class1 cla; void ds() { this.button1.Text = "def"; } private void button1_Click(object sender, EventArgs e) { cla = new Class1(this, ds); cla.run2(); } Class1类里的代码 public delegate void Del1(); public Del1 _del1; public Class1(Form1 f1, Del1 del) { this._del1 = del; } public delegate void Del2(); public Del2 _del2; public Class1(Form2 f2, Del2 del) { this._del2 = del; } public void run1() { Thread th = new Thread(a); th.Start(); } public void run2() { Thread th = new Thread(b); th.Start(); } public void a() { try { _del1();//不为空,可以执行 } catch (Exception e) { MessageBox.Show("a中的方法:\n"+e.ToString ()); } } public void b() { try { _del1();//问题在这,这里委托的方法为空,为什么,上面的怎么不为空? _del2(); } catch (Exception e) { MessageBox.Show("b中的方法:\n" + e.ToString()); } } 问题:在Class1 类里(有注释)。很急,求各位大神帮帮忙。 问题的要义就是在自定义的类里新起一条线程来调用窗体的控件,我是通过委托的方法执行,但在传这个方法(需要委托的方法)的参数时,在Class1的构造方法中检验是可以传进来的,但调用的时候就为空了。 再次求各位大神帮帮忙。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页