开发高级 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中…

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

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

使用loadrunner编写webservice接口请求

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

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

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

iOS开发那些事--创建基于故事板的iOS 6的HelloWorld

基于故事板的HelloWorld工程 Storyboard&#xff08;故事板&#xff09;是用来替代xib的技术&#xff0c;也是iOS 5最重要的新特性之一。我们用Storyboard&#xff08;故事板&#xff09;重构HelloWorld。 使用故事板重构HelloWorld 勾选“Use Storyboards”项。 工程创建完成之…

基于美国人口数据分析

https://github.com/jakevdp/PythonDataScienceHandbook 英文看不懂的话请自行选择中文翻译版转载于:https://www.cnblogs.com/Lucifer77/p/10741538.html

MySQL innodb每行数据长度的限制

今天在使用MySQL innodb时&#xff0c;create table时&#xff0c;报出这样的一个错误: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs 查阅MySQL的官方资料才发现&…

Hibernate实体JSONObject化时遇到的问题

2019独角兽企业重金招聘Python工程师标准>>> ###在对Hibernate持久化的对象进行JSON化的时候&#xff0c;出现了几个问题。 第一个是因为在对象中有相互引用&#xff0c;如A->B,B.set->A这样的一对多关系&#xff0c;使得在遍历构造JSON时&#xff0c;产生了死…

截取中英文字符串

代码 functionsubstr(str, len){if(!str ||!len) { return; }//预期计数&#xff1a;中文2字节&#xff0c;英文1字节vara 0;//循环计数vari 0;//临时字串vartemp ;for(i0;i<str.length;i){if(str.charCodeAt(i)>255){//按照预期计数增加2a2; }else{ a; }//如果增加计数…

mysql概述

MySql大致分为三层结构&#xff1a; 第一层&#xff1a;客户端并非MySql所独有&#xff0c;例如&#xff1a;连接处理、授权认证、安全等功能均在这一层处理 第二层&#xff1a;核心服务包括查询解析、分析、优化、缓存、内置函数(比如 : 时间、数学、加密等函数)&#xff0c;所…

团队项目-需求分析

团队作业-需求分析 这个作业属于哪个课程https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass2这个作业的要求在哪里https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass2/homework/3105团队名称快乐小分队这个作业的目标完成英语学习app&#xff0c;尽量…

REMarkerClusterer

2019独角兽企业重金招聘Python工程师标准>>> REMarkerClusterer 创建和管理大量的标记每个缩放级别的集群。REMarkerClusterer 受苹果的照片应用程序在iPhone上的启发&#xff0c;模仿它的行为提供分组和取消分组集群的动画。 转载:http://www.adobex.com/ios/sourc…

corosync+openais+pacemaker+web

corosync 和openais 各自都能实现群集功能&#xff0c;但是功能比较简单&#xff0c;要想实现功能齐全、复杂的群集&#xff0c;需要将两者结合起来.corosync 和openais 各自都能实现群集功能&#xff0c;但是功能比较简单&#xff0c;要想实现功能齐全、复杂的群集&#xff0c…

解构领域驱动设计(三):领域驱动设计

在上一部分&#xff0c;分层架构的目的是为了将业务规则剥离出来在单独的领域层中进行实现。再回顾一下领域驱动设计的分层中应用层代码的实现。 Override public void pay(int orderId, float amount) {DesignerOrder order designerOrderRepository.selectByKey(orderId); …

iOS 打包.framework(包括第三方、图片、xib、plist文件)详细步骤及需要注意的地方...

https://www.cnblogs.com/yk123/p/9340268.html // 加载自定义名称为Resources.bundle中对应images文件夹中的图片// 思路:从mainbundle中获取resources.bundleNSString *strResourcesBundle [[NSBundle mainBundle] pathForResource:”Resources” ofType:”bundle”];// 找到…

SQL优化准则

1. 在长时间运行的查询和短查询中使用事务 如果预期有一个长时间运行的查询&#xff0c;并且有大量的数据输出时&#xff0c;开发者就应该在BEGIN TRAN 和END TRAN之间使用事务。 这样事务会在缓冲区缓存为独立事务&#xff0c;并会被分配特定内存&#xff0c;以此来提高处理…

预祝大家2011农历新年快乐,宏“兔”大展,心想事成~

预祝大家2011农历新年快乐&#xff0c;宏“兔”大展&#xff0c;心想事成&#xff5e; 又是一年新年到&#xff0c;预祝大家2011农历新年快乐&#xff0c;宏“兔”大展&#xff0c;心想事成&#xff5e; _____________________________________________________ 以下是附带的……

MySQL中的表压缩功能

MySQL版本&#xff1a;8.0.22 os&#xff1a;linux ubuntu 语言&#xff1a;c、c 在MySQL中支持3种类型的表压缩&#xff0c;依次为&#xff1a;传统压缩、TPC压缩、字典压缩。 第一种&#xff1a;传统压缩 传统的表压缩方式是在MySQL5.0.7之前使用的&#xff0c;现在已经废…

net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案

本文目录1. Net下日志记录2. NLog的使用 2.1 添加nuget引用NLog.Web.AspNetCore 2.2 配置文件设置 2.3 依赖配置及调用 2.4 日志类型介绍 2.5 产生的日志文件3. 基于Microsoft.Extensions.Logging封装 3.1 添加引用Microsoft.Extensions.Logging 3.2 实现…