php 用户控件,UserControl 用户自定义控件 ASP.NET

关于用户自定义控件,想必大家已经非常熟悉了。虽然说经常用过,但是只是简单的使用而已。在这里再次总结一下Asp.net中的UserControl,以便下次使用时

能够得心应手。本文将会介绍以下内容:

1,什么是UserControl?

2,如何定义一个UserControl?

3,如何使用UserControl?

4,如何通过UserControl属性来控制html?

5,如何实现string?

1,什么是UserControl?

关于UserControl的解释MSDN,跟Wikipedia都有介绍:

说白了,UserControl的存在就是为了重用html代码。有点类似php的include或者require,但是它比include或require更加灵活,它不当只是

单纯的引入代码,而且通过设置UserControl的属性来对html代码进行控制,从而更好的实现代码复用。基本UserControl的使用方法更aspx页面

是一样的,但是UserControl不可以通过url来访问,只能在页面或者其它用户控件中访问。

2,如何定义一个简单UserControl?

新建UserControl方法:右键asp.net web项目->添加->添加新项->Web->Web用户控件。打开控件的后台代码,我们可以看到,控件

继承于System.Web.UI.UserControl类。新建好的控件除了后缀名更asp.net不同之外,其它结构都一样,用法也基本一致。

这是,你就可以在ascx文件添加html代码了。

3,如何使用UserControl?

在页面中使用UserControl只需要在页面的头部添加Register代码段:

src表示用户控件所在的相对路径。

添加完上述代码段之后,就可以你需要使用的地方使用了。

使用方法如下,我们可以看到uc1就是上面定义的tagprefix,Demo就是上面定义的tagname,由于用户控件也是一种服务端控件

因此我们这里必须加上runat="server",否则.net会认为是html标签。

4,如何自定义属性来控制UserControl的html?

第2,3部分已经介绍了如何新建以及使用一个简单的用户控件。但是,上面的例子只能满足对于简单html的复用,比如说一些

头部信息或底部信息。但对于一些复杂的模块,显然我们需要一些属性来控制它。比如说:我们定义一个用户控件,

该控件需要用户可以自定义主题。即用户希望能够这样的使用:

39449009_1.jpg

那么该怎么实现呢?首先,我们的第一印象就是,Theme应该是一个enum类型,可供用户选择,因此,我们首先定义一个Theme的枚举

public enum Theme

{

Brown = 10,

Cyan = 20,

Gray = 30,

Green = 40,

Leaf = 50,

Plain = 60,

Purple = 70

}

OK,枚举有了,那么我们应该如何将该枚举变成UserControl中可设置的选项呢?在UserControl的后台代码中(即ascx.cs文件),

我们只需为该控件类定义一个public的共有变量即可。因此,我们只要在后台类文件中,添加如下代码就可以实现上述需要:

public Theme ThemeName;

我们可以通过私有成员来设置初始值,这时候代码就变成这样:

private Theme _ThemeName = Theme.Cyan;

public Theme ThemeName

{

get { return this._ThemeName; }

set { _ThemeName = value; }

}

此时,用户可以通过属性来设置Theme了,Theme在页面中设置后,用户控件就可以通过Theme来控制它的html代码中的样式了。

5,如何实现string?

这个是本文中要讲的重点。在使用用户控件的过程中,有时候是一个模块(如下图),我只需要重用这个框,而这个框里的内容

是要自定义的。那么我们要怎么办呢?首先我们想到的是属性,但是我们不可能将一大串的html代码作为属性传递过去,

这样代码就太恶心了。因此我们就想到了标题的那种方式。将html夹在控件中间。还是接着上面所说的例子,这时,我们希望

用户可以这样调用:

hello world!

通过google,我找到了解决办法。asp.net提供了ITextControl接口,通过该接口我们就可以实现上述的功能。因此,我们需要做的

就是:第一步,让UserControl实现ITextControl接口。第二步,实现ITextControl的Text字段。第三步,重写Control类中的AddParsedSubObject方法。

假设我们有好几个这样的控件,因此,我们将以上三步实现的内容抽象到一个类中,我们暂且叫做DemoWidget,代码如下:

[ParseChildren(false)]

public class DemoWidget : System.Web.UI.UserControl, ITextControl

{

[PersistenceMode(PersistenceMode.InnerDefaultProperty)]

public virtual string Text

{

get

{

object obj2 = this.ViewState["Text"];

if (obj2 != null)

{

return (string)obj2;

}

return string.Empty;

}

set

{

if (this.HasControls())

{

this.Controls.Clear();

}

this.ViewState["Text"] = value;

}

}

protected override void AddParsedSubObject(object obj)

{

if (obj is LiteralControl)

{

HtmlContent.Append(((LiteralControl)obj).Text);

this.Text = HtmlContent.ToString();

}

else

{

if (obj != null)

{

HtmlContent.Append(GetControlHtml(obj as Control));

this.Text = HtmlContent.ToString();

}

}

}

protected StringBuilder HtmlContent = new StringBuilder();

protected string GetControlHtml(Control ctl)

{

StringBuilder sb = new StringBuilder();

StringWriter tw = new StringWriter();

HtmlTextWriter writer = new HtmlTextWriter(tw);

ctl.RenderControl(writer);

sb.Append(writer.InnerWriter.ToString());

return sb.ToString();

//base.AddParsedSubObject(new LiteralControl(tmpStr));

//this.Text = tmpStr;

}

}

我们来看一下,DemoWidget是如何实现上述的三个步骤的。很明显第一步已经完成。

第二步我们可以看到也实现了ITextControl的Text字段,Text字段就是用于保存夹在用户控件中间的文本,从代码中我们可以看到,我将这些文本信息保存到viewstate中。

而Text上方的属性[PersistenceMode(PersistenceMode.InnerDefaultProperty)]

又表示什么呢?msdn的解释如下:

InnerDefaultProperty 指定属性在 ASP.NET 服务器控件中保持为内部文本。还指示将该属性定义为元素的默认属性。只能指定一个属性为默认属性。

(http://msdn.microsoft.com/zh-cn/library/system.web.ui.persistencemode.aspx)

也就是说,Text将作为DemoWidget的默认属性使用,而且只能有一个这样的属性。

第三步,重写AddParsedSubObject方法

为什么要重新AddParsedSubObject方法呢?我们首先添加一个空的AddParsedSubObject方法,设置一个断点,然后调试,我们可以发现,当DemoWidget中间有文本时,

都会调用该函数,因此,这里我们可以将html赋值给Text。默认,传递进该函数的对象是LiteralControl类型的。因此我们实现如下代码:

该方法的具体解释请查看msdn:http://msdn.microsoft.com/zh-cn/library/system.web.ui.control.addparsedsubobject.aspx

protected override void AddParsedSubObject(object obj)

{

if (obj is LiteralControl)

{

this.Text = ((LiteralControl)obj).Text;

}

这里还需要注意的是:我们必须为DemoWidget类添加属性[ParseChildren(false)],ParseChildren属性表示是否将服务器控件标记内的元素解释为属性,因此,这里应该为false。

http://msdn.microsoft.com/zh-cn/library/system.web.ui.parsechildrenattribute.aspx

好了,之前提到的三步我们都已经完成了,可是我发现类还有其它代码,其它代码又是干嘛的呢?此时,我们发现如果刚刚三步虽实现了一开始提出的需求,

但是,上述类还有一定的局限性,就是控件标记内只能包含html文本,当控件标记内需要包含另外一个控件的时候就有问题了。

hello world!

hello world!

由于控件标记中包含了其它控件,因此,AddParsedSubObject中的参数obj就有可能是子控件类型,因此我们必须修改AddParsedSubObject函数,并新建HtmlContent成员,用于保存子控件的html代码

然后再将该子控件生成的html代码赋值给控件的Text属性,GetControlHtml方法就是用于获取子控件生成的html代码。而AddParsedSubObject则变成如下所示:

protected override void AddParsedSubObject(object obj)

{

if (obj is LiteralControl)

{

HtmlContent.Append(((LiteralControl)obj).Text);

this.Text = HtmlContent.ToString();

}

else

{

if (obj != null)

{

HtmlContent.Append(GetControlHtml(obj as Control));

this.Text = HtmlContent.ToString();

}

}

}

这时,你就可以随意在UserControl标签里添加任何东西了,你可以添加html代码,也可以添加自定义控件,甚至还可以添加asp.net服务端控件。

嗯,关于UserControl的内容就介绍到这里,有什么讲得不对的地方请大家指正,同时也期望得到大家的鼓励。

这里是源代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值