当前位置: 首页 > 编程日记 > 正文

ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

第四章 组合控件开发CompositeControl

大家好,今天我们来实现一个自定义的控件,之前我们已经知道了,要开发自定义的控件一般继承三个基

类:Control,WebControl,还有一个就是今天要说的CompositeControl。

系列文章链接:

ASP.NET自定义控件组件开发 第一章 待续

ASP.NET自定义控件组件开发 第一章 第二篇 接着待续

ASP.NET自定义控件组件开发 第一章 第三篇

ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件

ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇

ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇

ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡

ASP.NET自定义控件组件开发 第五章 模板控件开发

ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性

ASP.NET2.0组件控件开发视频 初体验

大家也许还记得,之前的开发的控件基本上都是我们自己从头到尾的写一些控件的标记,如<table.....>之类的,

而且还有一个大的问题:我们为了使得我们的控件更加的好用,专业,我们还实现了大量的接口,和自己写很多的事件.这样

开发控件的时间就加大了。其实我们可以利用ASP.NET中已经有的控件,经过我们包装,实现我们自定义控件。大家可能认

为这和用户控件差不多的,但是继承CompositeConytol的控件的自定义控件的灵活性和复用行更好,而且还还添加样式。

还一个更加重要的就是我们不必要实现接口,比如,引发回传的IPostBackEventHandler接口,接受数据的

IPostBackDataHandler接口。大家还记得我们之前开发控件中的的那个Button还要申明name为 this.UniqueID ,

现在我们都不需要了,因为我们要包装的那些服务器的控件,如TextBox,他们都已经实现了这些。

本章准备开发一个大家都熟知的Login登录控件。

大家先看看效果:

其实分析起来,这个控件是由一些已有的控件组合而成的,分别是:

两个Label,两个TextBox,和一个Button

下面我们就来开发:

首先,还是先继承CompositeControl;

ContractedBlock.gifExpandedBlockStart.gifCode
1  public class Login:CompositeControl

然后把就申明我们要组合的控件,如上所说的:

ContractedBlock.gifExpandedBlockStart.gifCode
1  #region 要组合的控件
2         Label lbUserName;
3         Label lbUserPassward;
4         TextBox txtUserName;
5         TextBox txtUserPassward;
6         Button submitButton;
7         #endregion

把控件申明了之后只要初始化,并且将这些控件整合成我们的Login 控件就可以了。这么做呢?

其实开发组合控件很简单,一般只要重写一个方法就可以了。这个方法就是来初始化并且整合那些已经申明了的小

控件的。如下:

ContractedBlock.gifExpandedBlockStart.gifCode
 1   #region 重写方法CreateChildControls
 2 
 3         protected override void CreateChildControls()
 4         {
 5             //清空控件,大家可以理解为:初始化一张白纸,好让我们来画画
 6 
 7             Controls.Clear();
 8 
 9            //初始化控件lbUserName
10             lbUserName = new Label();
11             lbUserName.Text = "用户名:";
12             lbUserName.ID = "lbUserName";
13             //把控件添加到我们的组合控件中
14             Controls.Add(lbUserName);
15 
16             //初始化控件lbUserPassward
17             lbUserPassward = new Label();
18             lbUserPassward.Text = "密  码:";
19             lbUserPassward.ID = "lbUserPassward";
20             Controls.Add(lbUserPassward);
21 
22               //初始化控件txtUserName 
23 
24             txtUserName = new TextBox();
25             txtUserName.ID = "txtUserName";
26             txtUserName.Width = Unit.Percentage(60);
27             Controls.Add(txtUserName);
28           
29             //初始化控件txtUserPassward 
30             txtUserPassward = new TextBox();
31             txtUserPassward.ID = "txtUserPassward";
32             txtUserPassward.Width = Unit.Percentage(60);
33             Controls.Add(txtUserPassward);
34 
35             //初始化控件 submitButton  
36             submitButton  = new Button();
37             submitButton.Text = "提交";
38             submitButton.CommandName = "Validate";
39             Controls.Add(submitButton);
40             
41             告诉编译器,控件已经初始化了
42             ChildControlsCreated = true;
43         }
44         #endregion

大家特别要注意,最后的那句ChildControlsCreated属性,一定要申明,因为在页面的声明周期的任何时候可能调

用上面的那个方法,如果不申明ChildControlsCreated,那么这个方法就会被反复的调用,那么我们控件的状态都会丢失。

如果申明了ChildControlsCreated=true,那么这个方法就调用一次。

经过上面的步骤之后,其实我们的控件就已经开发完成了。

可能我们还想进一步的向我们ASP.NET的标准的Login控件靠拢.那么我们的控件还缺少什么?

属性,事件!!!

以前我们定义属性都是用的ViewState["..."],但是这里就不同了。因为我们的控件是有很多的小的控件组

合起来的,比如,我们修改“用户名:”的那个Label,我们想改的是那个Label的属性,还是看看效果图:

改前的图:                                                       改后的图

 

就是说,我们想把子控件的属性如Text,name等等,把这些属性上升呈现为组合控件Login的属性。

怎么做?

也很简单的:如下:

ContractedBlock.gifExpandedBlockStart.gifCode
 1  public string UserNameLabelText
 2         {
 3             get
 4             {
 5                 EnsureChildControls();
 6                 return lbUserName.Text;
 7             }
 8             set
 9             {
10                 EnsureChildControls();
11                 lbUserName.Text = value;
12             }
13         }

这样我们就把那个显示用户名的Label的Text属性显示为了Login控件的UserNameLabelText属性。大家要注意

EnsureChildControls(); 这个方法的调用。其实是个保险的:确保我们要显示属性的那个控件已经创建,已经初始化了。

大家可以根据需要显示更加多的属性。也可以自己定义一些属性,还是像以前那样,可以用ViewState[''.."]

如果到这里为止,就差不多了。大家可以按按照上面的方法来写控件。

大家可以看见,控件的呈现很乱。那些Label.TextBox都布局的很乱。其实你可以根据需要来将上面的那些控件排列

的更加好看些,只要重写一个方法就行了:

ContractedBlock.gifExpandedBlockStart.gifCode
1 protected override void RenderContents(HtmlTextWriter writer)

还是像之前一样,我们想把控件用一个Table来布局,先这样

ContractedBlock.gifExpandedBlockStart.gifCode
1  protected override HtmlTextWriterTag TagKey
2         {
3             get
4             {
5                 return HtmlTextWriterTag.Table;
6             }
7         }

然后再把那些Label,TextBox,Button放到table的行和列中就行了。如下:

ContractedBlock.gifExpandedBlockStart.gifCode
 1 protected override void RenderContents(HtmlTextWriter writer)
 2         {
 3 
 4             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 5 
 6             writer.RenderBeginTag(HtmlTextWriterTag.Td);
 7             lbUserName.RenderControl(writer);
 8             writer.RenderEndTag();//td的结束
 9 
10             writer.RenderBeginTag(HtmlTextWriterTag.Td);
11             txtUserName.RenderControl(writer);
12             writer.RenderBeginTag();
13 
14             writer.RenderBeginTag();//tr的结束
15 
16             //***********************************************
17 
18             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
19 
20             writer.RenderBeginTag(HtmlTextWriterTag.Td);
21             lbUserPassward .RenderControl(writer);
22             writer.RenderEndTag();//td的结束
23 
24             writer.RenderBeginTag(HtmlTextWriterTag.Td);
25             txtUserPassward .RenderControl(writer);
26             writer.RenderBeginTag();
27 
28             writer.RenderBeginTag();//tr的结束
29            
30             //***********************************************
31 
32             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
33 
34             writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
35             writer.AddAttribute(HtmlTextWriterAttribute.Align, "center");
36             writer.RenderBeginTag(HtmlTextWriterTag.Td);
37             submitButton.RenderControl(writer);
38             writer.RenderBeginTag();
39 
40             writer.RenderBeginTag();//tr的结束
41 
42                       
43 
44 
45         }

这样,我们的控件就写完了。

我们的控件还差事件。我们在下篇将“事件的冒泡”。

顺便做个调查:大家想看开发控件的视频吗,我正在录制。

完整的代码:如下:

ContractedBlock.gifExpandedBlockStart.gifCode
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.Web;
  5 using System.Web.UI;
  6 using System.Web.UI.WebControls;
  7 using System.ComponentModel;
  8 
  9 namespace LoginControl
 10 {
 11     public class Login:CompositeControl,IPostBackDataHandler
 12     {
 13         #region 要组合的控件
 14         Label lbUserName;
 15         Label lbUserPassward;
 16         TextBox txtUserName;
 17         TextBox txtUserPassward;
 18         Button submitButton;
 19         #endregion
 20        
 21 
 22         #region 重写方法CreateChildControls
 23 
 24         protected override void CreateChildControls()
 25         {
 26             Controls.Clear();
 27 
 28            //初始化控件lbUserName
 29             lbUserName = new Label();
 30             lbUserName.Text = "用户名:";
 31             lbUserName.ID = "lbUserName";
 32             //把控件添加到我们的组合控件中
 33             Controls.Add(lbUserName);
 34 
 35             //初始化控件lbUserPassward
 36             lbUserPassward = new Label();
 37             lbUserPassward.Text = "密  码:";
 38             lbUserPassward.ID = "lbUserPassward";
 39             Controls.Add(lbUserPassward);
 40            
 41 
 42             txtUserName = new TextBox();
 43             txtUserName.ID = "txtUserName";
 44             txtUserName.Width = Unit.Percentage(60);
 45             Controls.Add(txtUserName);
 46 
 47             txtUserPassward = new TextBox();
 48             txtUserPassward.ID = "txtUserPassward";
 49             txtUserPassward.Width = Unit.Percentage(60);
 50             Controls.Add(txtUserPassward);
 51 
 52             submitButton  = new Button();
 53             submitButton.Text = "提交";
 54             submitButton.CommandName = "Validate";
 55             Controls.Add(submitButton);
 56 
 57             ChildControlsCreated = true;
 58         }
 59         #endregion
 60         #region 将组合的子控件的属性 呈现为 组合控件的属性
 61 
 62         public string UserNameLabelText
 63         {
 64             get
 65             {
 66                 EnsureChildControls();
 67                 return lbUserName.Text;
 68             }
 69             set
 70             {
 71                 EnsureChildControls();
 72                 lbUserName.Text = value;
 73             }
 74         }
 75 
 76         public string UserPasswardLabelText
 77         {
 78             get
 79             {
 80                 EnsureChildControls();
 81                 return lbUserPassward.Text;
 82             }
 83             set
 84             {
 85                 EnsureChildControls();
 86                 lbUserPassward.Text = value;
 87             }
 88         }
 89 
 90         public string SubmitButtonText
 91         {
 92             get
 93             {
 94                 EnsureChildControls();
 95                 return submitButton.Text;
 96             }
 97             set
 98             {
 99                 EnsureChildControls();
100                 submitButton = value;
101             }
102         }
103 
104 
105         #endregion
106 
107         #region 组合控件呈现的样式
108         protected override HtmlTextWriterTag TagKey
109         {
110             get
111             {
112                 return HtmlTextWriterTag.Table;
113             }
114         }
115 
116         protected override void RenderContents(HtmlTextWriter writer)
117         {
118 
119             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
120 
121             writer.RenderBeginTag(HtmlTextWriterTag.Td);
122             lbUserName.RenderControl(writer);
123             writer.RenderEndTag();//td的结束
124 
125             writer.RenderBeginTag(HtmlTextWriterTag.Td);
126             txtUserName.RenderControl(writer);
127             writer.RenderBeginTag();
128 
129             writer.RenderBeginTag();//tr的结束
130 
131             //***********************************************
132 
133             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
134 
135             writer.RenderBeginTag(HtmlTextWriterTag.Td);
136             lbUserPassward .RenderControl(writer);
137             writer.RenderEndTag();//td的结束
138 
139             writer.RenderBeginTag(HtmlTextWriterTag.Td);
140             txtUserPassward .RenderControl(writer);
141             writer.RenderBeginTag();
142 
143             writer.RenderBeginTag();//tr的结束
144            
145             //***********************************************
146 
147             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
148 
149             writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
150             writer.AddAttribute(HtmlTextWriterAttribute.Align, "center");
151             writer.RenderBeginTag(HtmlTextWriterTag.Td);
152             submitButton.RenderControl(writer);
153             writer.RenderBeginTag();
154 
155             writer.RenderBeginTag();//tr的结束
156 
157                       
158 
159 
160         }
161         #endregion
162 
163         
164 
165     }
166 }
167 

相关文章:

[C++对象模型][6]sizeof与对象内存布局

有了前面几节的铺垫&#xff0c;本节开始摸索C的对象的内存布局&#xff0c;平台为windows32位VS2008。 一 内置类型的size 内置类型&#xff0c;直接上代码&#xff0c;帮助大家加深记忆&#xff1a; Codevoid TestBasicSizeOf() { cout << __FUNCTION__ << e…

Linux负载均衡实现

配置之前清空所有服务器防火墙规则iptables -F关闭selinux&#xff1a;1、/usr/sbin/sestatus -v ##如果SELinux status参数为enabled即为开启状态SELinux status: enabled2、getenforce ##也可以用这个命令检查关闭SELinux&#xff1a;1…

【bzoj2770】YY的Treap 权值线段树

题目描述 志向远大的YY小朋友在学完快速排序之后决定学习平衡树&#xff0c;左思右想再加上SY的教唆&#xff0c;YY决定学习Treap。友爱教教父SY如砍瓜切菜般教会了YY小朋友Treap&#xff08;一种平衡树&#xff0c;通过对每个节点随机分配一个priority&#xff0c;同时保证这棵…

第二章 数据类型、运算符与表达式

#include <stdio.h> #include <stdlib.h>int Add(int a,int b) {return ab; }int main() {int x,y,sum 0;printf("Input two integers:\n");scanf("%d%d",&x,&y);sum Add(x,y);printf("sum %d\n",sum);return 0; }计算圆…

从设计原则谈软件开发(二)

最近一直在一个培训公司做着极为无聊的培训&#xff0c;所以一直都没有时间上网。今天突然发现这里可以上无线&#xff0c;嘿嘿&#xff0c;就上来继续把这个文章完成。 上次说到了设计原则中的单一职责原则&#xff0c;今天时间比较紧&#xff0c;我就继续往下写&#xff0c;也…

Npm环境依赖重置

需要彻底删除node_modules 然后npm install 如果无法删除node_modules文件&#xff0c;可以试试这个&#xff1a; 安装RimRaf&#xff1a; npm install rimraf -g 并在项目文件夹中删除node_modules文件夹&#xff1a; rimraf node_modules 然后你可以去npm install转载于:http…

MySQL的information_schema

在一次清空一张比较大的表时&#xff08;在清空前占用400多兆&#xff09;&#xff0c;发现该表中记录为0条但是空间并没有被释放&#xff0c;采用下面方式可查看占用情况 -- 查询各个数据库占用磁盘的情况 select TABLE_SCHEMA, concat(truncate(sum(data_length)/1024/1024,2…

编写spring应用

测试类自动注入失败&#xff1a;RunWith(SpringRunner.class)详解 CtrlAltDelete键&#xff0c;打开任务管理器&#xff0c;结束占据8080端口的Tomcat进程。 HomeController.java <!DOCTYPE html> <html xmlns"http://www.w3.org/1999/xhtml"xmlns:th&quo…

[导入]Learning.ASP.NET 2.0.with.AJAX.pdf(14.14 MB)

ASP.NET 2.0的AJAX无疑是最快&#xff0c;最有效&#xff0c;最可靠和最佳的方式支持创建交互式Web应用程序上市。结合开发工具&#xff0c;可以从Microsoft &#xff0c;免费和商业&#xff0c;这是难以置信轻松地创建网站&#xff0c;看看伟大的表现良好。最重要的是&#xf…

c# IO线程 打造 定时打开指定程序

用IO以及线程轻松实现 定时器 &#xff0c;在指定的时间打开指定的程序&#xff1a;&#xff09; 首先是如何实现定时&#xff1f;这可以单独的用个线程&#xff0c;在时间到的时候打开程序 然后是如何打开程序 &#xff0c;用Process.Start就可以了 最后就是如何把程序列表保存…

Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

Memcached Memcached 是一个高性能的分布式内存对象缓存系统&#xff0c;用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数&#xff0c;从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程&#xf…

jQuery中的常用内容总结(一)

jQuery中的常用内容总结(一) 前言 不好意思(✿◠‿◠)&#xff0c;由于回家看病以及处理一些其它事情耽搁了&#xff0c;不然这篇博客本该上上周或者上周写的&#xff1b;同时闲谈几句&#xff1a;在这里建议各位开发的童鞋&#xff0c;如果有疾病尽快治疗&#xff0c;不要拖&a…

你需要眼光和资格

机上遇到一男人&#xff0c;操北京口音&#xff0c;三十二三&#xff0c;婚否不详&#xff0c;容貌体面。 优势&#xff1a;技术好&#xff0c;聪明&#xff0c;没坏心&#xff0c;乐观 劣势&#xff1a;有点懒&#xff0c;自傲&#xff0c;责任心与意志力指数一般 其所谓“恰当…

嵌入式系统基础了解

1.一个启动 .s文件&#xff08;start.s&#xff09;&#xff0c;至少需要包含三个段: ;//堆栈段 ; //中断向量表 ; //代码段 参考代码&#xff1a; stack_size EQU 0x200 ;…

BFD与IGP快速收敛应用测试

cqmmx&#xff0c;2008-9-10 1、背景介绍 目前对网络稳定性影响较大的一般是链路中断、节点失效等故障&#xff0c;而常规的慢Hello机制检测耗时较长&#xff0c;且常用IGP&#xff08;ISIS和OSPF&#xff09;在默认配置情况下&#xff0c;收敛速度很慢&#xff0c;一般需要几十…

rsa证书ssh登陆服务器

好久不用&#xff0c;又生疏了。 今晚实操了一下&#xff0c;作一个记录。 使用rsa的密钥对登陆linux服务器&#xff0c;主要是为了安全。 这种证书级别的登陆&#xff0c;比最复杂的root用户名和帐号的安全性都要高一个等级。 至少服务器不会被暴破(暴力破解)。 ~~~~~~~~~~~~~…

简单数据结构(队列 栈 树 堆 )

基础知识 基本概念 程序 算法 数据结构数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。 常见…

cannot access a closed file

用上传控件上传文件时&#xff0c;当执行SaveAs()时出错&#xff0c;异常为cannot access a closed file&#xff1b; 当传小文件没有异常&#xff0c;当超过80k时就出上述异常&#xff0c;后来发现要将Web.config里增加 <!--设置上传附近的大小--> <httpRuntime …

实验四-常用图像增强方法

1、采用二维中值滤波函数medfilt2 对受椒盐噪声干扰的图像滤波&#xff0c;窗口分别采用3*3,5*5,7*7 i imread(D:\study\third_down\ImageProcessing\work\work_one\flower.jpg); I rgb2gray(i); J imnoise(I,salt & pepper,0.04); K1 medfilt2(J,[3 3]);%对矩阵I进行…

商贸通服装鞋帽版客户端无法连接服务器的问题(自己遇到的,已解决)

今天给一客户装“商贸通服装鞋帽版”&#xff0c;客户机是xp&#xff0c;服务器是win2003,装好后在连接服务器是总是报“无法连接服务器”之类的错&#xff0c;但是客户机和服务器双向都可以ping的通&#xff0c;而且双方的防火墙都已关闭&#xff0c;没有第三方防火墙&#xf…

【转】Visual C#创建和使用ActiveX组件

开发基于.net平台上的程序员是很难从本质上把Visual C#和ActiveX组件联起来&#xff0c;虽然在使用Visual C#开发应用程序时&#xff0c;有时为了快速开发或者由于.Net Framework SDK的不完整&#xff0c;还需要借助ActiveX。但即使如此&#xff0c;也很难把二者联系起来。其中…

Why Sleeping May Be More Important Than Studying

Why Sleeping May Be More Important Than Studying转载于:https://www.cnblogs.com/Lamfai/p/10441451.html

测试开发板与主机之间通过串口收发数据(uart.c/uart.h )

usart.c: #include "usart.h"// U1_TX: PA9 // U1_RX: PA10 void usart_init(void) {//1. GPIO口的配置RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); GPIO_InitTypeDef p;p.GPIO_Mode GPIO_Mode_AF;p.GPIO_Pin GPIO_Pin_9 | GPIO_Pin_10;p.GPIO_PuPd G…

卷积神经网络--CNN

1.人工神经网络 神经网络由大量的节点&#xff08;或称“神经元”、“单元”&#xff09;和相互连接而成。每个神经元接受输入的线性组合&#xff0c;进行非线性变换&#xff08;亦称激活函数activation function&#xff09;后输出。每两个节点之间的连接代表加权值&#xff0…

基于WinCE的I2C驱动程序设计

http://www.mcu123.com/news/Article/rtos/WinCE/200607/88.html 引言 随着以计算机技术、通信技术和软件技术为核心的信息技术的迅速发展&#xff0c;嵌入式系统在各行业得到了广泛的应用&#xff0c;极大地推动了行业的渗透性应用。嵌入式系统是“以应用为中心、以计算机技…

poj2965-poj2965-The Pilots Brothers' refrigerator

方法同poj1753&#xff0c;但用在这题就TLE了&#xff0c;以下是TLE版本&#xff1a; Code1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#define MAXSTATE 65536 5#define MAXSIZE 16 6#define ALLOPEN 0 7 8//队列结构体 9type…

sysctl -p详解

个人一般sysctl -p 或sysctl -a比较多使用 sysctl配置与显示在/proc/sys目录中的内核参数&#xff0e;可以用sysctl来设置或重新设置联网功能&#xff0c;如IP转发、IP碎片去除以及源路由检查等。用户只需要编辑/etc/sysctl.conf文件&#xff0c;即可手工或自动执行由sysctl控…

定制简单的Linux系统

定制简单的Linux系统 制作思路&#xff1a; 新加一块硬盘&#xff0c;设置两个分区&#xff0c;一个存/boot&#xff0c;一个存/&#xff0c;创建文件系统并格式化。要注意&#xff0c;现在我们家的硬盘是要可以拔下来安装到其他机器上使用的&#xff0c;否则就没有意义了。试…

UCOS同步与互斥

代码为老师教授。 /* ********************************************************************************************************* * EXAMPLE CODE * * (c) Copyright 2013; Micrium, Inc.; We…

Spring学习八

1&#xff1a; Tomcat容器四个等级&#xff1f; Container&#xff0c; Engine&#xff0c; Servlet容器&#xff0c; Context 真正管理Servlet的容器是Context容器&#xff1a;一个context对应一个web工程。 <Context path"/projectOne " docBase"D:\proje…