Home > Asp.Net > asp.net 创建web自定义控件.

asp.net 创建web自定义控件.

最近因为工作需要写了一个asp.net的web的自定义控件. 总结一下心得.
写控件的过程中, 遇到了几个问题.
1. 资源的引用, 比如说控件中要使用js, 图片什么的, 应该如此去处理.
2. 在写控件的时候, 设置属性的时候, visual studio 总是崩溃, 找了几个小时才找到原因.
3. 就是如何响应外部的postback.

如何创建自定义控件.
如果是visual studio2005的话, 需要创建Visual C# – Windows – Web Control Library 项目.
如果是Visual Studio 2008的话, 是要创建 Visual C# – Web – ASP.NET Server Control 这一个项目.
项目建立好之后, 如果需要在项目中使用JavaScript的话, 则需要继承INamingContainer接口.
然后, 具体继承什么扩展, 是根据你的需要来的, 如果你需要增加Dropdownlist,则继承自Dropdownlist. Textbox, Label等等,同样道理.
我这里需要的是一个组合控件. 即是一个文本框与一个下拉列表的组合. 因此我选择继承自CompositeControl
然后override CreateChildControls的方法, 就可以在里面进行编程了. 不过需要注意的是, 一定要把 base.CreateChildControls(); 这一行给禁用掉, 否则你的控件什么都显示出不来.
如果需要将来在引用控件的时候, 在工具栏上面, 控件左侧显示一个小图票, 可以设置ToolboxBitmap选项.

[ToolboxBitmap(typeof(DropDownList))]
public partial class SearchableList : CompositeControl, INamingContainer
{
        protected override void CreateChildControls()
        {//这里书写控件
            Textbox txt = new Textbox();
            txt.Text = "Hello CompositeControl";
            txt.ID = "txt";
            txt.TextChanged += new EventHandler(txt_TextChanged); //后面会用到.
            txt.AutoPostback = this.TextboxPostBack;
            this.Controls.Add(txt);
           //base.CreateChildControls(); //一定要删除,否则控件不会显示内容.
        }
}

当然, 还需要的是定义控件的属性.如果需要控件显示在属性菜单上面. 则需要设置上面的标签.例子如下.

        [Bindable(true)]
        [Category("Appearance")] //哪一个分类里面, 可以自己定义
        [DefaultValue("")] //默认的值
        [Localizable(true)] //是否本地化.
        public string Text
        {
            get
            {
                String s = (String)ViewState["Text"];
                return ((s == null) ? String.Empty : s);
            }
 
            set
            {
                ViewState["Text"] = value;
            }
        }

这里有几点要注意的.
1. 如果属性的类型是一个自定义类型的话, 该类一定是 [Serializable]
2. 所有的属性的上面都需要定义标签. 最起码也要定义一个[Browsable(false)]或者是[Browsable(true)]
3. 并不是所有的属性都可以设置为[Browsable(true)], 像dropdownlist的selectindex,如果设置了, 在Design的时候, 选中控件, 会导致VS崩溃.
4. 属性一定要放在ViewState里面, 否则的话, 定义的状态不会永久保存, 在postback之后,会消失.

如何响应外部的POSTBACK.
要响应外问的POSTBACK, 首先要注册事件. 然后写根据前面已经注册的事件,来写处理程序.

public event EventHandler TextChanged;
protected virtual void textbox_TextChanged(object sender, EventArgs e)
 {
        if (TextChanged != null)
        {
             TextChanged(this, e);
         }
 }

这里需要注意2点.
1. Textbox的Autopostback需要设置为True, 当然, 可以通过属性来设置.
2. 在Web 页面定义事件的时候, 不要把自定义控件的事件注册过程写在if(!Page.IsPostback)里面, 这样会丢失事件. 正在研究更好解决的方法.

[Bindable(true), Category("MyCategory"), Localizable(true), Browsable(true)]
public bool TextboxPostBack
 {
       set { ViewState["istestpostback"] = value; }
       get
        {
            return ViewState["istestpostback"] == null ? false : (bool)ViewState["istestpostback"];
        }
 }

外部资源的引用.
其实外部资源的引用相对简单

[assembly: WebResource("NameSpaceLibrary.JavaScript.js.js", "text/javascript", PerformSubstitution = true)]
namespace NameSpaceLibrary
{
     //然后调用的时候,使用
     this.Page.ClientScript.RegisterClientScriptResource(this.GetType(), "NameSpaceLibrary.JavaScript.js.js");
}

这里很简单.NameSpaceLibrary命名空间, JavaScript是文件夹, js.js是文件名. 可以根据自己的情况更改.
这里需要注意的是, 在创建好了文件之后,如js文件, 右击js文件, 属性, 一定要选择Build Action: Embedded Resource , 编译进dll里面. 这样在调用的时候, 就不用额外的把js文件复制给别人了~


related post

  1. May 31st, 2010 at 16:02 | #1

    小站呼隆隆来访,博主本该热烈欢迎,哈哈,无奈博主不在,小站留个脚印方便下次再来。。。。
    o(∩_∩)o

  1. No trackbacks yet.