开发高级 Web 部件

       通过用户控件实现 Web 部件相当容易,但是也有一些弊端:

  • 受限的重用:如果不手动复制 .ascx 文件到其他 Web 应用程序的目录下,就不能动态添加这些控件到其他 Web 应用程序的页面中。
  • 受限的个性化:用户控件的个性化仅限于常用的属性,如标题、标题 URL 等。你不能获取用户控件的自定义属性,该属性保存在个性化存储里,只有从 Web 部件派生而来的类才能有这类功能
  • 更好的呈现和行为控制:当使用自定义服务器控件时,你对呈现过程有更好的控制,而且可以更加动态的生成用户界面。

       因此,有时候需要将高级 Web 部件实现为从 System.Web.UI.WebControls.WebParts.WebPart 派生而来的服务器控件

 

       创建一个 Web 部件的步骤如下:

  1. 从 WebPart 派生
  2. 添加自定义属性,通过特性指定哪些属性可以被用户编辑,以及在个性化存储里哪些需要按照每个用户存储,哪些又被所有用户共享
  3. 编写初始化和加载代码,覆盖你需要的任何初始化过程。通常,会覆盖 OnInit()和 CreateChildrenControls()
  4. 加载阶段完成后,控件将触发它们的事件,你可以在自定义 Web 部件里为子控件添加事件处理程序
  5. 在呈现阶段开始前,要完成最后的任务,如设置控件的属性和基于其所绑定到的数据源构建控件的结构。
  6. 最后,必须编写代码来呈现 Web 部件。必须覆盖 RenderContents()方法,它被基类在呈现边框、标题栏和带有动词的标题菜单的操作之间调用。

1. 开始之前,创建强类型的 DataSet

       在开始深入到开发 Web 部件的细节之前,必须为方便的访问存在数据库中的数据添加几个特别的组件,这些组件将用来完成本文的代码示例。右击项目添加一个 DataSet,命名为 CustomerSet,拖曳 Customer 和 CustomerNotes 表至 DataSet 的设计界面上。如下图:

image

       两个强类型的 DataSet 扩展了 DataSet 类并提供了强类型的表适配器。右击 CustomerNotes 表,添加一个查询用于获取某位客户的注解,该查询有一个参数 CustomerId。

image

       总之,应该总是在开始创建实际的用户界面组件之前创建业务层和数据访问层,当然,业务层和数据访问层是可以跨不同应用程序的,就像这个强类型的 DataSet 一样。

 

2. 自定义 WebPart 的骨架

       创建一个继承自 WebPart 的自定义类。引入命名空间 System.Web.UI.WebControls.WebParts 可以方便的访问 Web Parts Framework。给 Web 部件添加一些属性。对类里的每一个属性过程,都可以指定这个属性是对每个用户个性化还是被所有用户共享,以及这个属性能否被用户访问

namespace Apress.WebParts.Samples
{
    public class CustomerNotesPart : WebPart
    {
        public CustomerNotesPart() { }
 
        [WebBrowsable(true)]
        [Personalizable(PersonalizationScope.User)]
        public string Customer { get; set; }
    }
}

       WebBrowsable 特性指定了这个属性对终端用户可见。Personalizable 特性指定了该属性的个性范围是基于每个用户的

 

3. 初始化 Web 部件

       你可以选择性的创建子控件,就像创建一个组合 Web 部件时所做的那样。如果不想在 RenderContents()方法内使用预置的控件,你可以自己呈现 Web 部件。但是,使用组合控件可以让事情变得简单很多,因为你不必担心 HTML 细节。

       要创建控件,必须覆盖 CreateChildControls()方法,如下所示:

private TextBox NewNoteText;
private Button InsertNewNote;
private GridView CustomerNotesGrid;
 
protected override void CreateChildControls()
{
    NewNoteText = new TextBox();
 
    InsertNewNote = new Button();
    InsertNewNote.Text = "Insert...";
    InsertNewNote.Click += InsertNewNote_Click;
 
    CustomerNotesGrid = new GridView();
    CustomerNotesGrid.HeaderStyle.BackColor = System.Drawing.Color.LightBlue;
    CustomerNotesGrid.RowStyle.BackColor = System.Drawing.Color.LightGreen;
    CustomerNotesGrid.AlternatingRowStyle.BackColor =
        System.Drawing.Color.LightGray;
    CustomerNotesGrid.AllowPaging = true;
    CustomerNotesGrid.PageSize = 5;
    CustomerNotesGrid.PageIndexChanging += CustomerNotesGrid_PageIndexChanging;
 
    Controls.Add(NewNoteText);
    Controls.Add(InsertNewNote);
    Controls.Add(CustomerNotesGrid);
}
 
void CustomerNotesGrid_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    // Insert Page Change Logic
    // ...
}
 
void InsertNewNote_Click(object sender, EventArgs e)
{ 
    // Insert new note here
    // ...
}

 

4. 加载数据和处理事件      

       这个 Web 部件的生命周期里的下一个阶段是加载阶段此时,可以连接到数据库加载数据到控件里。要完成这些,必须覆盖 OnInit()和 OnLoad()方法,或者捕获 Web 部件的 Init 和 Load 事件。两种做法效果相同。但是当覆盖 OnLoad() 时,需要调用 Base.OnLoad()以便基类的加载功能也被执行。因此,有必要建立一次事件处理程序并捕获自定义控件的事件,以便你不会忘记这点

// Add some method into the control's constructor
public CustomerNotesPart()
{
    this.Init += new EventHandler(CustomerNotesPart_Init);
    this.Load += new EventHandler(CustomerNotesPart_Load);
    this.PreRender += new EventHandler(CustomerNotesPart_PreRender);
}

 

       现在,先编写从数据库中加载数据的功能,然后在事件里调用它。引入 CustomerSetTableAdapters 命名空间编码会简短一些,这个命名空间是用原来设计的强类型的 DataSet 创建的

void BindGrid()
{
    // 确定服务器控件是否包含子控件。如果不包含,则创建子控件。
    
 
    CustomerNotesTableAdapter adapter = new CustomerNotesTableAdapter();
    if (Customer.Equals(string.Empty))
    {
        CustomerNotesGrid.DataSource = adapter.GetData();
    }
    else
    {
        CustomerNotesGrid.DataSource = adapter.GetDataByCustomer(Customer);
    }
}
 
void CustomerNotesPart_Load(object sender, EventArgs e)
{
    // Initialize web part properties
    this.Title = "Customer Notes";
    this.TitleIconImageUrl = "NotesImage.jpg";
}
 
void CustomerNotesPart_Init(object sender, EventArgs e)
{
    // Don't try to load data in design mode
    if (!this.DesignMode)
    {
        BindGrid();
    }
}

      一定要记得调用 EnsureChildControls()方法,因为你并不确定 ASP.NET 什么时候实际调用 CreateChildControls()来创建子控件,ASP.NET 会在需要的时候创建这些控件。因此,你需要确保在这个方法里的控件可用。

 

       现在,数据已经加载到网格了。在生命周期的下一阶段,ASP.NET 运行库处理事件。你的自定义 Web 部件必须捕获之前添加的提交新注解到数据库的 InertNewNote 按钮的事件和改变页面的 CustomerNotesGrid 的事件:

void CustomerNotesGrid_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    CustomerNotesGrid.PageIndex = e.NewPageIndex;
}
 
void InsertNewNote_Click(object sender, EventArgs e)
{
    CustomerNotesTableAdapter adapter = new CustomerNotesTableAdapter();
 
    // if NoteID is an identity column, you needn't insert it.
    adapter.Insert(Customer, DateTime.Now, NewNoteText.Text);
 
    // Refresh the grid with the new row as well
    BindGrid();
}

 

       最后,必须在代码的另一个地方也加载数据到 GridView。一旦有人修改了 Customer 属性的值,Web 部件就要显示与这个新选择的客户相关的信息:

private string _Customer;
[WebBrowsable(true)]
[Personalizable(PersonalizationScope.User)]
public string Customer
{
    get
    {
        return _Customer;
    }
    set
    {
        _Customer = value;
        if (!this.DesignMode)
        {
            EnsureChildControls();
            CustomerNotesGrid.PageIndex = 0;
            CustomerNotesGrid.SelectedIndex = -1;
            BindGrid();
        }
    }
}

 

5. 最后的呈现

       到此为止,已经初始化了 Web 部件,创建了控件,编写了加载数据的代码,并且捕获了控件事件。那么,该呈现 Web 部件了。在呈现之前,你可以在控件上设置影响最后呈现的最后的属性。比如,如果用户还没有初始化 Customer 属性,你应该禁用 InsertNewNote 按钮

       GridView 现在可以创建必需的 HTML 控件来显示其所绑定的数据了(数据的加载之前的事件中已经完成了)。要完成这些,需要调用 DataBind()方法:

void CustomerNotesPart_PreRender(object sender, EventArgs e)
{
    if (Customer.Equals(string.Empty))
    {
        InsertNewNote.Enabled = false;
    }
    else
    {
        InsertNewNote.Enabled = true;
    }
 
    CustomerNotesGrid.DataBind();
}

 

       在 RenderContents()里,可以创建 HTML 代码来设置 Web 部件的布局。如果不覆盖这个方法,Web 部件将按照控件在 CreateChildControls()方法里被插入到 Web 部件的 Controls 集合中的顺序来自动呈现。所以,你要覆盖这个方法来创建一个更好的,美观的,基于表的布局:

protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
    writer.Write("<table>");
 
    writer.Write("<tr>");
    writer.Write("<td>");
    NewNoteText.RenderControl(writer);
    InsertNewNote.RenderControl(writer);
    writer.Write("");
    writer.Write("</tr>");
    writer.Write("<tr>");
    writer.Write("<td>");
    CustomerNotesGrid.RenderControl(writer);
    writer.Write("");
    writer.Write("</tr>");
 
    writer.Write("");
}

 

6. 更多定制步骤

       如前所述,使用 IWebPart 接口,实现的自定义 Web 部件可以覆盖属性,如标题和描述。此外,你还可以通过为其赋值(最好在 Load 里)来为 Web 部件的其他属性指定默认值。甚至可以覆盖来自 Web 部件的默认属性和方法的实现

public override bool AllowClose
{
    get
    {
        return false;                    ;
    }
    set
    {
        // Don't want this to be set.
    }
}

 

       这样,已经创建了一个 Web 部件,其中调用者不能通过外部的属性设置来覆盖其行为。你已经完成了对 Web 部件哪些能做、哪些不能做的定制。

 

7. 使用 Web 部件

       在 Web 部件页面的顶部使用 <%@ Register%> 指令注册 Web 部件:

<%@ Register TagPrefix="apress" Namespace="Apress.WebParts.Samples" %>

       接着,在 WebPartZone 控件里使用该 Web 部件:

<asp:WebPartZone runat="server" ID="MainZone" >
    <zonetemplate>
        <uc1:Customers ID="MyCustomers" runat="server" OnLoad="MyCustomers_Load" />
        <apress:CustomerNotesPart ID="MyCustomerNotes" runat="server" />
    </zonetemplate>
</asp:WebPartZone>

       现在调试前一篇的示例,效果如下:

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462832.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

强一致性和弱一致性的区别

一致性包括强一致性和弱一致性&#xff1a; 弱一致性&#xff1a;可以理解为CAP定律中的不一致现象。但是经过一定的时间会达到最终一致性 强一致性: 包含线性一致性和顺序一致性。 因此强一致性不一定是线性一致性&#xff0c;但线性一致性一定是强一致性

Juqery Html(),append()等方法的Bug

标题中说是jquery中的Bug&#xff0c;只是个人这么认为&#xff0c;先申明一下&#xff01; 这几天在做动态加载图片热区&#xff0c;我用Ajax获取到了area标签&#xff0c;这里有多个area,在IE8和FF里测试正常&#xff0c;可一到IE7,和IE6里面就显示不正常了。后来发现jquery中…

Cantor定理的一种好表述

今天我在A course on Borel sets 一书中看到了Cantor定理的一种好表述.我很喜欢这种表述.在很多书中&#xff0c;康托定理是这样表述的&#xff1a; 自然数集合的所有子集形成的集合是不可数集. 也有这样表述的: $2^{\mathbb{N}}$是不可数集. 不过在A course on Borel sets 中…

分页类与前台和后台的调用方法

using System;using System.Text; namespace WebDemo.Common{ public class LaomaPager { /// <summary> /// /// </summary> /// <param name"pageSize">一页多少条</param> /// <param name"currentPage">当前页</par…

MySQL中rename一个view对应的SQL语句

OS&#xff1a;linux ubuntu 最近在对MySQL数据库开发的过程中&#xff0c;需要修改一个view的名字&#xff0c;但是找了许久才找到对应的SQL&#xff0c;切记不是alter&#xff0c;而是rename table .... 在MySQL中&#xff0c;如果想要rename 视图的名字&#xff0c;需要使用…

SharePoint2007 配置MOSS基于AD的Forms验证

公司上边要求使用Forms验证方式登陆到MOSS系统 于是经过研究测试成功了, 这次上边又要求用户必须为AD用户 查了很多资料 经过了一番周折 终于测试成功了,无奈网上文章转载的太多, 差错太多,特将本人亲自测试的具体步骤贴出来 与大家一起进步 有什么不对的地方 还希望多提出宝贵…

ubuntu 12.04 nginx+ mono-fastcgi-server

mono是.NET在Linux下的的开源实现&#xff0c; 主要的运行方式分为两种apache mod_mononginx fastcgi (mono)考虑到nginx性能更好&#xff0c;这里讲述第二种实现方法因为Ubuntu 提供了完整的mono软件包支持&#xff0c;因此本文尝试在Ubuntu 12.04下搭建安装mono和fastcgi-s…

std::make_unique<T>和std::make_shared<T>

更建议使用&#xff1a;std::make_unique<T>构造unique_ptr对象&#xff1b;std::make_shared<T>构造shared_ptr对象 std::make_shared是C11的一部分&#xff0c;std::make_unique不是&#xff0c;它在C14才纳入标准库。如果你使用的是C11&#xff0c;不用忧伤&…

maven 聚合工程 用spring boot 搭建 spring cloud 微服务 模块式开发项目

项目的简单介绍: 项目采用maven聚合工程 用spring boot 搭建 spring cloud的微服务 模块式开发 项目的截图: 搭建开始: 能上图 我少打字 1.首先搭建maven的聚合工程 1.1创建聚合工程的父模块 1.2设置父模块的POM文件 主要是配置 spring boot版本&#xff0c;spring cloud 版本&…

Cheatsheet: 2010 12.13 ~ 12.23

Web Slow Website? 6 Ways to Speed it Up MongoDB Monitoring: Keep in it RAM Minify JavaScript on the fly - Cached JavaScript minification on the fly – ASP.NET and HttpHandler What To Do When Your Website Goes Down Methods to hide email addresses from page…

epoll原理详解

原文链接&#xff1a;https://blog.csdn.net/daaikuaichuan/article/details/83862311 设想一个场景&#xff1a;有100万用户同时与一个进程保持着TCP连接&#xff0c;而每一时刻只有几十个或几百个TCP连接是活跃的(接收TCP包)&#xff0c;也就是说在每一时刻进程只需要处理这…

使用loadrunner编写webservice接口请求

1、使用工具&#xff1a; loadrunner12&#xff0c;本实例截图中都是loadrunner12工具 2、操作步骤&#xff1a; 1)、新建脚本&#xff0c;选择Web Services协议&#xff1a; 2)、选择工具栏&#xff1a; 3)、点击Import&#xff0c;输入wsdl地址&#xff1a;测试代码用的地址&…

C#格式化字符串净化代码的方法

C#格式化字符串净化代码的方法&#xff0c;在C#编程中&#xff0c;字符串类型是最容易处理出错的地方&#xff0c;其代价往往也很昂贵&#xff0c;在.NET Framework中&#xff0c;字符串是一个不可变的类型&#xff0c;当一个字符串被修改后&#xff0c;总是创建一个新的副本&a…

实验二《Java面向对象程序设计》实验报告

一、实验内容 初步掌握单元测试和TDD理解并掌握面向对象三要素&#xff1a;封装、继承、多态初步掌握UML建模熟悉S.O.L.I.D原则了解设计模式 二、实验步骤 &#xff08;一&#xff09;单元测试 1.三种代码&#xff1a;伪代码、测试代码、产品代码需求&#xff1a;在一个MyUtil类…

Java 包装类 自动装箱和拆箱

包装类&#xff08;Wrapper Class&#xff09; 包装类是针对于原生数据类型的包装。 因为有8个原生数据类型&#xff0c;所以对应有8个包装类。 所有的包装类&#xff08;8个&#xff09;都位于java.lang下。 Java中的8个包装类分别是&#xff1a;Byte, Short, Integer, Long, …

Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结

知识背景&#xff1a; 210.25.132.181属于IP地址的ASCII表示法&#xff0c;也就是字符串形式。英语叫做IPv4 numbers-and-dots notation。 如果把210.25.132.181转换为整数形式&#xff0c;是3524887733&#xff0c;这个就是整数形式的IP地址。英语叫做binary data。&#xff0…

MySQL中alter table range partition

最近在用MySQL开发新功能时&#xff0c;使用到了alter table range partition的功能&#xff0c;在此总结下mysql innodb支持的alter table range partition相关功能。mysql的版本是8.0.22, os: linux ubuntu 对alter range partition的操作主要由以下几个&#xff1a; analy…

可恶,谁占用了我的80端口?

下午在室友的本本上上网&#xff0c;突然想看一个新闻系统&#xff0c;他的本上没有安装环境&#xff0c;于是下载一个wamp,安装。运行wamp&#xff0c;晕...怎么只有1个服务在运行&#xff0c;导致我的localhost打不开&#xff0c;看了一下mysql服务运行正常&#xff0c;apach…

laravel命令

新建控制器 php artisan make:controller IssuesController 新建控制器并自动生成对应RESTful风格路由相关CURD方法 php artisan make:controller IssuesController -r 新建一个迁移文件 php artisan make:migration create_issues_table --createissues 回滚上一次迁移的内容 …

CMakeList.txt中设置一个可变的变量的值(bool)

在CMakeList.txt中有个bool变量&#xff0c;在debug模式下需要设置为OFF&#xff0c;在其他模式(release、thread、leak)下设置为ON&#xff0c;需要在makefile中将该值设置不同的值&#xff0c;CMakeList.txt中增加的代码如下&#xff1a; IF(CMAKE_BUILD_TYPE STREQUAL &quo…