【问题标题】:Simple Custom Web Control简单的自定义 Web 控件
【发布时间】:2013-02-28 17:55:27
【问题描述】:

您好,我正在设计一个继承自 aspx 下拉列表的自定义 .net Web 控件。 这个想法是有一个下拉列表,它将显示直到当前年份的年份值。我希望能够设置控件可以开始的“StartYear”属性,或者使用默认日期。我能够创建此控件,但它始终使用默认日期。看来我无法在后面的代码中使用aspx代码中的属性设置。我的前端代码是....

<customControls:YearDropDownList StartYear="2000" ID="ddlYear" runat="server"/>

后面的代码是

using System;
using System.ComponentModel;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.WebControls;

    namespace customControls {
    [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
    [DefaultProperty("StartYear")]
    public class YearDropDownList : DropDownList
    {
        public YearDropDownList() {
            for (int i = Int32.Parse(StartYear); i <= DateTime.Now.Year; i++)
            {
                this.Items.Add(new ListItem(i.ToString(), i.ToString()));
            }
        }
        public string StartYear {
            get{
                String s = (String)ViewState["StartYear"];
                return ((s == null) ? "2009":s);
            }
            set{
                ViewState["StartYear"] = value;
            }
        }
    }
    }

【问题讨论】:

    标签: c# asp.net .net web-controls


    【解决方案1】:

    在我看来,在构造函数中重新生成列表是没有意义的。在控件被实例化时,ViewState 可能还不会被填充(虽然我不确定),因此您将始终使用您的默认值。

    这是我要做的:

    [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
    [DefaultProperty("StartYear")]
    public class YearDropDownList : DropDownList
    {
        public string StartYear
        {
            get
            {
                String s = (String)ViewState["StartYear"];
                return ((s == null) ? "2009" : s);
            }
            set
            {
                ViewState["StartYear"] = value;
                RegenerateList();
            }
        }
    
        // Defer regenerating the list until as late as possible    
        protected void OnPreRender(EventArgs e)
        {
            RegenerateList();
            base.OnPreRender(e);
        }
    
        public void RegenerateList()
        {
            // Remove any existing items.
            this.Items.Clear();
            for (int i = Int32.Parse(StartYear); i <= DateTime.Now.Year; i++)
            {
                this.Items.Add(new ListItem(i.ToString(), i.ToString()));
            }
        }
    }
    

    【讨论】:

    • 这不起作用,问题是 setter 永远不会被调用
    • 这是您通过调试确定的(未调用 setter)吗?
    • 是的,如果我以后有空闲时间,我想在一个简单的页面上尝试一下,让它工作,然后进入用户控件。我认为 .NET 页面生命周期存在问题,但目前没有时间深入研究此问题
    • 如何实例化用户控件?它是在布局中指定的还是您使用的是LoadControl
    【解决方案2】:

    这样设置属性时需要重新生成列表;

    [ToolboxData("<{0}:YearDropDownList runat=\"server\" StartYear=\"[StartYear]\"></{0}:YearDropDownList>")]
    [DefaultProperty("StartYear")]
    public class YearDropDownList : DropDownList
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            RegenerateList();
        }
        public string StartYear
        {
            get
            {
                String s = (String)this.ViewState["StartYear"];
                return s ?? "2009";
            }
            set
            {
                ViewState["StartYear"] = value;
                RegenerateList();
            }
        }
        public void RegenerateList()
        {
            Items.Clear();
            for (int i = Int32.Parse(this.StartYear); i <= DateTime.Now.Year; i++)
            {
                this.Items.Add(new ListItem(i.ToString(), i.ToString()));
            }
        }
    }
    

    我已经测试并验证了上面的代码,它绝对有效。我确实注意到的一件有趣的事情是,我能够在一段时间内重现您的问题,因为属性设置器没有被击中。我通过右键单击解决方案并单击清理解决了这个问题。清理解决方案后,我再次右键单击解决方案,但这次选择了重建。这似乎解决了属性设置器问题。

    【讨论】:

    • 从构造函数调用函数与在构造函数中编写代码有何不同?
    • @JBone 不是,而是在构造函数和属性中编写了两次代码,我将它移到了自己的方法中,并从两个位置调用它。为什么不需要写两次代码?
    • 啊在setter里没看到,我试试这个
    • 还是不行,好像setter没有被调用
    • @JBone 我已经复制了原始问题并相应地更新了我的帖子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 2011-10-02
    • 2018-03-06
    • 1970-01-01
    • 2014-02-11
    相关资源
    最近更新 更多