WEB自定义控件设计时在ASPX页面中生成子控件问题

waki 2003-12-03 12:56:31
想实现象微软的IE webcontrol中的treeview控件一样,在设计时点击notes属性,加入Note子控件,并且在ASPX页面中于设计时就加入了<iewc:item .../>之类的代码,请问如何实现的,能否给个简单点的例子。微软的例子实在是太长了,找不到要点。
...全文
72 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
waki 2003-12-04
  • 打赏
  • 举报
回复
多谢LevinForum指点,确实,ILIST接口的大部分成员我都是直接拷贝而没有修改的,应该是可从CollectionBase继承过来。
另问一点:Remove()方法不是必须的吗?
waki 2003-12-04
  • 打赏
  • 举报
回复
To: xiandaliu
我定义的noteItemCollection就是一个控件集合呀。
我试过,不加此特性是可以的,[ParseChildren(bool, string)]
可能它默认就是[ParseChildren(false)]吧。
LevinForum 2003-12-04
  • 打赏
  • 举报
回复
像你那样实现IList很麻烦的.
实际上一个类型化的Collection继承System.Collections.CollectionBase就是
ItemType this[int index]
Add(ItemType)
是必须的.
xiandaliu 2003-12-04
  • 打赏
  • 举报
回复
是否需要实现ControlCollection,不知道楼主考虑过没有??
xiandaliu 2003-12-04
  • 打赏
  • 举报
回复
缺少[ParseChildren(bool, string)]
waki 2003-12-04
  • 打赏
  • 举报
回复
终于搞定了,这个例子对我帮助很大:http://www.codeproject.com/aspnet/ecoolwebpanelbar.asp
虽然它在我机上运行不了。:D
下面我再将我的经验总结下,以免同仁走弯路。
1。将子控件单独定义为类,如public class noteItem{},为了不让此子控件在整个DLL被拖入工具箱时不显示,可以使用此特性:[ToolboxItem(false)]
2.子控件应有集合类,引用System.Collection ,定义:
public class noteItemCollection:Ilist
3.实现IList接口成员:
CopyTo(),Count,IsSynchronized,SyncRoot,GetEnumerator,Add(),Clear(),Contains,IndexOf,Insert,IsFixedSize,IsReadOnly,Remove,RemoveAty,this[int]。
4.在主类中定义加入特性:
[DesignerSerializationvisibility(DesignerSerializationvisibility.Content)]
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
[Editor(typeof(CollectionEditor),typeof(UITypeEditor))]
如果实现了自己的编辑器,可将typeof(CollectionEditor)换成自己的,可以是WinForm的,可参考TreeView源码。
5.在主类中定义一集合变量和一ArrayList变量,如:
private noteItemCollection _notes;
private ArrayList al;
在构造函数内写:
{
al = new ArrayList();
_notes = new noteItemCollection(al);
}

后天散分。
monkeys 2003-12-04
  • 打赏
  • 举报
回复
都是强人,学习
goody9807 2003-12-03
  • 打赏
  • 举报
回复
up
LevinForum 2003-12-03
  • 打赏
  • 举报
回复
这里帖出生成Control的Facade类的代码:


namespace Sample
{
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

public class FacadeCodeAspx : System.Web.UI.Page
{
protected System.Web.UI.WebControls.TextBox TextBox1;

private void Page_Load(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
}

#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion


protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

TextBox1.Text=new FacadeCodeMaker(typeof(Calendar)).ToString();
}

}
}
namespace Sample
{
using System;
using System.Collections;
using System.ComponentModel;
using System.Text;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.UI;

public class FacadeCodeMaker
{
Type type;
PropertyDescriptorCollection pdc;
StringBuilder sb=new StringBuilder();
System.CodeDom.Compiler.IndentedTextWriter w;
string classname;
public FacadeCodeMaker(Type t)
{
type=t;
pdc=TypeDescriptor.GetProperties(type);
w=new System.CodeDom.Compiler.IndentedTextWriter(new StringWriter(sb));
classname=type.Name+"Facade";



GenCode();
}
void GenCode()
{
w.WriteLine("[System.ComponentModel.ToolboxItem(false)]");
w.WriteLine("public class "+classname+" : System.ComponentModel.Component {");
w.Indent++;

GenAttributeClasses();

w.WriteLine(type.FullName+" inst;");
w.WriteLine("public "+type.FullName+" Get"+type.Name+"()");
w.WriteLine("{");
w.Indent++;
w.WriteLine("return inst;");
w.Indent--;
w.WriteLine("}");
w.WriteLine("public "+classname+"("+type.FullName+" "+type.Name+")");
w.WriteLine("{");
w.Indent++;
w.WriteLine("inst="+type.Name+";");
w.Indent--;
w.WriteLine("}");
w.WriteLine("override public string ToString(){return string.Empty;}");

foreach(PropertyDescriptor pd in pdc)
{
if(!pd.IsBrowsable)
continue;
if(pd.SerializationVisibility==DesignerSerializationVisibility.Hidden)
continue;
if(pd.PropertyType==typeof(object))
continue;

if(pd.Name=="ID")
continue;

GenProperty(pd);
}

w.Indent--;
w.WriteLine("}");
}
void GenAttributeClasses()
{
w.WriteLine("[System.AttributeUsage(System.AttributeTargets.Property)]");
w.WriteLine("public class CategoryAttribute:System.ComponentModel.CategoryAttribute{");
w.Indent++;

w.WriteLine("public CategoryAttribute(string propertyName):base(GetValue(propertyName)){}");
w.WriteLine("static string GetValue(string propertyName){");
w.Indent++;

w.WriteLine("return System.ComponentModel.TypeDescriptor.GetProperties(typeof("+type.FullName+"))[propertyName].Category;");

w.Indent--;
w.WriteLine("}");

w.Indent--;
w.WriteLine("}");


w.WriteLine("[System.AttributeUsage(System.AttributeTargets.Property)]");
w.WriteLine("public class DescriptionAttribute:System.ComponentModel.DescriptionAttribute{");
w.Indent++;

w.WriteLine("public DescriptionAttribute(string propertyName):base(GetValue(propertyName)){}");
w.WriteLine("static string GetValue(string propertyName){");
w.Indent++;

w.WriteLine("return System.ComponentModel.TypeDescriptor.GetProperties(typeof("+type.FullName+"))[propertyName].Description;");

w.Indent--;
w.WriteLine("}");

w.Indent--;
w.WriteLine("}");
}
void GenProperty(PropertyDescriptor pd)
{
foreach(Attribute attr in pd.Attributes)
{
if(attr is DefaultValueAttribute)
{
#region DefaultValueAttribute
DefaultValueAttribute a=(DefaultValueAttribute)attr;
object v=a.Value;
string cstr=null;
if(v==null)
{
cstr="null";
}
else if(v is String)
{
cstr="@\""+v.ToString().Replace("\"","\"\"")+"\"";
}
else if(v is bool)
{
cstr=v.Equals(true)?"true":"false";
}
else if(v is Int16||v is Int32||v is Int64)
{
cstr=v.ToString();
}
else if(v is Single)
{
cstr=v.ToString()+"f";
}
else if(v is Double)
{
cstr=v.ToString()+"d";
}
else
{
cstr="typeof("+v.GetType().FullName+"),@\""+TypeDescriptor.GetConverter(v).ConvertToString(v).ToString().Replace("\"","\"\"")+"\"";
}
w.WriteLine("[System.ComponentModel.DefaultValue("+cstr+")]");
#endregion
}
if(attr is PersistenceModeAttribute)
{
PersistenceModeAttribute a=(PersistenceModeAttribute)attr;
w.WriteLine("[System.Web.UI.PersistenceMode(PersistenceMode."+a.Mode.ToString()+")]");
}
}

w.WriteLine("[Category(\""+pd.Name+"\")]");
w.WriteLine("[Description(\""+pd.Name+"\")]");
w.WriteLine("[System.ComponentModel.NotifyParentProperty(true)]");
w.WriteLine("[System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility."+pd.SerializationVisibility+")]");
w.WriteLine("public "+pd.PropertyType.FullName+" "+pd.Name);
w.WriteLine("{");
w.Indent++;

w.WriteLine("get");
w.WriteLine("{");
w.Indent++;
w.WriteLine("return inst."+pd.Name+";");
w.Indent--;
w.WriteLine("}");

if(!pd.IsReadOnly)
{
w.WriteLine("set");
w.WriteLine("{");
w.Indent++;
w.WriteLine("inst."+pd.Name+"=value;");
w.Indent--;
w.WriteLine("}");
}

w.Indent--;
w.WriteLine("}");
}

public override string ToString()
{
return sb.ToString();
}

}
}







LevinForum 2003-12-03
  • 打赏
  • 举报
回复
这是属性设计时序列化的问题.
学习ListControl是怎样做的就好了:

public MyCtrl:WebControl
{

[DesignTimeSerializeVisibility(DesignTimeSerializeVisibility.Content)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ListItemCollection MyItems
{
get
{
return _items;
}
}
ListItemCollection _items;

}

上面的Attribute名可能写错了。
不过序列化子属性就用这两个就够了。

顺便提提,如果Property类型是Control,那么vs.net不会把它们序列化.
我的解决方法是用代码生成Control的一个代理类来处理子属性.

可以参考
http://www.lostinet.com/en/lwsamplecs/?framesrc=combocalendar/
中的CalendarFacade
下载
http://www.lostinet.com/en/lwsamplecs.zip (临时,过了这段时间不下就没有机会咯~~)
waki 2003-12-03
  • 打赏
  • 举报
回复
另一本关于控件的书是wrox的,但在wrox网站上竟然找不到此书的源码,谁能告诉在哪下载?
waki 2003-12-03
  • 打赏
  • 举报
回复
我有那本书,反复看了相关章节,但还是有些不明白的,书上主要说的是ASPX中已有子控件代码时的解析。但对如何加入子控件只是提了一下,说得不详细,始终未得要领。
大可山人 2003-12-03
  • 打赏
  • 举报
回复
5728这本书我正进行中,很好!!
saucer 2003-12-03
  • 打赏
  • 举报
回复
you need to write a CollectionEditor, see the HotSpotCollectionEditor example in

Developing Microsoft ASP.NET Server Controls and Components
by Nikhil Kothari and Vandana Datye

you download the code here
http://www.microsoft.com/mspress/books/companion/5728.asp#Companion%20Content

or look into
eCoolWebPanelBar - Outlook style Web Panel Bar
http://www.codeproject.com/aspnet/ecoolwebpanelbar.asp
waki 2003-12-03
  • 打赏
  • 举报
回复
多谢各位大侠,ListControl的例子,我昨晚在其它贴上看到了,并试了一下,确实可以序列化子控件。但它的子控件为组件,后来我将它换成webcontrol,没有成功,所以就发了这个贴。今晚再仔细研究研究。

62,041

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧