65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 用户控件 - 通知一个控件中的更改在另一个控件中

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.39/5 (20投票s)

2002 年 3 月 13 日

6分钟阅读

viewsIcon

198599

downloadIcon

2615

本教程介绍如何使用委托模型来通知一个 ASP.NET 用户控件中的更改在另一个用户控件中。

SiteHeader UserControl

SiteHeader UserControl

在我们之前的两篇文章中,用户控件 - I用户控件 - II,我们讨论了一些编写简单 ASP.Net UserControls 的基本概念。为了继续深入,我们尝试更进一步,扩展之前讨论的概念,编写一对使用 delegate 机制进行通信的控件。

示例做什么

为了演示两个通信控件的概念,我们编写了两个简单的控件。一个控件 SiteBanner,显示一个广告横幅;另一个控件 SiteBannerManager,更改横幅的图片 URL 和链接 URL。当您单击 SiteBannerManager 控件中的按钮时,它会引发一个事件,SiteBanner 控件对此做出响应并更改 URL。

我们如何做到这一点

正如我们所说,一个控件引发事件,另一个控件响应它。这种通信是如何发生的?在 .NET Framework 中,事件的处理和引发是通过 delegate 机制进行的。我们不会详细讨论这个机制。这里有一个关于 delegate 机制的良好解释,以及一个漂亮且具有说明性的示例。

在这个机制中涉及的两个控件扮演以下角色。

  • SiteBannerManager - 事件引发者
  • SiteBanner - 事件消费者

以下是发生通信的事件序列。

  • 事件源 SiteBannerManager 响应控件上按钮的 Click 事件。
  • 在此按钮控件的事件处理程序中,会构造一个 BannerChangeEventArgs 对象,其中包含新的图片和链接 URL 信息。
  • 然后 SiteBannerManager 控件引发 BannerChange 事件。
  • 事件消费者 SiteBanner 控件将自己注册到 SiteBannerManager 控件,以便在发生更改时得到通知。
  • SiteBannerManager 控件引发 BannerChange 事件时,消费者控件通过它注册到事件引发者的委托接收通知。
  • 作为对事件通知的响应,SiteBanner 控件从 BannerChangeEventArgs 对象中提取新的链接信息,并将新值分配给它的 asp:HyperLink 控件。
  • 刷新后的页面会显示带有新导航链接的新横幅。

实现细节

到目前为止一切顺利。让我们讨论一下这个完整的事件流机制是如何实现的。event/delegate 机制在 .NET Framework 文档中有很好的描述。诀窍在于如何根据您的需求进行扩展。我们将尝试按照文档中的顺序进行解释,以便您阅读文档时能够理解。

SiteBannerManager - 事件引发者

首先,我们将编写将引发事件的控件,该事件将通知图片和导航 URL 已更改。

事件处理程序的通用定义如下。

public void MyEventHandler(object sender, MyEventArgs args);

事件处理程序的第二个参数封装了正在引发的事件的特定数据。因此,第一步是确定需要随事件传递哪些信息。在我们的例子中,我们希望通知所有客户端新的图片和导航 URL。我们创建 BannerChangeEventArgs 类,它派生自 System.EventArgs 类。该类有两个属性,用于存储两个 URL 字符串的值。

public class BannerChangeEventArgs : EventArgs

然后提供事件处理程序的定义。

public delegate void BannerChangeEventHandler(object sender, 
                                              BannerChangeEventArgs e);

这是重要部分。在 SiteBannerManager 类中添加此事件处理程序的实例。此实例将为消费者提供连接点,在那里他们将注册他们的事件处理程序。并提供引发事件的函数。

public abstract class SiteBannerManager : System.Web.UI.UserControl
{
    .
    .
    public event BannerChangeEventHandler BannerChange;
    protected void OnChangeBannerImg(object sender, System.EventArgs e)
    {
        BannerChangeEventArgs args = new BannerChangeEventArgs();
        args.ImageURL = wndImgURLTxt.Text;
        args.LinkURL = wndLinkURLTxt.Text;
        OnBannerChange(args);
    }
    protected virtual void OnBannerChange(BannerChangeEventArgs args)
    {
        if (BannerChange != null)
        {
            BannerChange(this, args);
        }
    }                                            
}

上面的代码提供了需要为引发事件提供的代码的概述。OnChangeBannerImg 是控件上按钮的 Click 事件的事件处理程序。当用户单击按钮时,将处理此事件。我们从两个 asp:Textbox 控件中提取新的 URL 字符串值,并将它们放入 BannerChangeEventArgs 对象。然后,控件为所有为处理事件而注册的委托引发事件。

SiteBanner - 事件消费者

事件引发者本身无法完成任何事情,除非有一个消费者会响应它引发的事件。如果 SiteBannerManager 对象的事件处理程序没有注册事件处理程序,那么在该控件中对 URL 所做的更改将不会对页面产生任何影响。

因此,我们需要编写一个消费者来处理 BannerChange 事件。这在 SiteBanner 类中完成。遵循以下步骤来实现事件处理:

事件消费者的首要责任是提供事件处理函数。此函数必须与事件引发者定义的事件处理程序具有相同的签名。这是 SiteBanner 类中事件处理程序的实现。

public void ChangeBannerImage(object sender, BannerChangeEventArgs args)
{
    if (args.ImageURL.Length != 0 &&
        args.LinkURL.Length != 0)
    {
        BannerHyperLink.ImageUrl = args.ImageURL;
        BannerHyperLink.NavigateUrl = args.LinkURL;
    }
}

此事件处理函数的参数与事件引发者类 SiteBannerManager 中定义的委托相同。

整合

现在我们有了一个引发事件的类和一个将处理已引发事件的类。让我们看看所有部件是如何连接在一起以发挥实际作用的。

我们一起构建了一个非常简单的 Web 窗体 BannerAds.aspx。它不做任何花哨的事情。它提供了一个占位符来添加我们创建的两个控件。正如我们在前面的文章中讨论过的,首先我们在页面的顶部添加对两个 UserControls 的引用。

<%@ Page language="c#" Codebehind="BannerAds.aspx.cs" 
         AutoEventWireup="false" Inherits="ASPNet_App.BannerAds" %>
<%@ Reference Control="./Controls/SiteBanner.ascx"%>
<%@ Reference Control="./Controls/SiteBannerControl.ascx"%>

然后我们为添加控件提供一个占位符。

<form id="BannerAds" method="post" runat="server">
    <asp:Panel Runat="server" ID="BannerDiv"></asp:Panel>
</form>

请注意,我们将 asp:Panel 占位符控件放在 form 标签内。这样做是必需的,因为我们在 SiteBannerManager 控件中有 asp:Textboxasp:Button 控件。为了处理这些控件引发的事件,它们必须定义在 form 标签内。如果您忘记这样做,请不用担心。您将收到一个运行时异常,提醒您这样做。

现在是真正将所有部件连接起来的时候了。首先,我们在 BannerAds 类的 Page_Load 方法中使用 LoadControl 方法加载两个控件。然后,我们将 ChangeBannerImage 方法注册为 SiteBannerManager 类的 BannerChange 事件的事件处理程序。以下是 BannerAds 类中 Page_Load 的实现,展示了这两个控件是如何连接在一起的。

Control bannerControl;
Control banner;
try
{
    bannerControl = LoadControl("Controls/SiteBannerControl.ascx");
    banner = LoadControl("Controls/SiteBanner.ascx");
    if (bannerControl != null)
    {
        ((SiteBannerControl)bannerControl).BannerChange +=
             new BannerChangeEventHandler(((SiteBanner)banner).ChangeBannerImage);
    }
    CreateBannerControlTable(bannerControl, banner);
}

现在,我们已准备好将这一切付诸实践。打开 BannerAds.aspx 页面。它将显示左侧的两个文本框和一个按钮,右侧的横幅。输入新图片和导航的新 URL,然后单击“更改横幅”按钮。您将看到右侧的横幅图片发生变化,前提是 URL 指向有效的图片文件。

我们还没有在文本框中添加验证器,以确保字符串不为空。我们将随着这个 UserControl 主题系列的文章一起更新代码。但我们确信这应该能让您对如何让用户控件响应其他控件引发的事件有一个很好的了解。

在接下来的日子里,我们将发布更多文章,演示 UserControl 开发的一些方面。因此,如果您有任何建议或希望演示某个功能,请随时通过 softomatix@pardesiservices.com 给我们写信,或通过 Softomatix 联系我们。

© . All rights reserved.