以下是我自定义的一个控件。现在有两个问题:
1。控件放到页面上后无法正常显示。但更改某一属性后就能显示出来,但在源码与设计视图之间切换后就不好使了。可是在运行状态下可以正常显示。
2。控件的VALUE等属性值为什么不更新。在属性设计器里就不好使,运行时点增加或减少按钮都没有反应。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;namespace GoldWisdom
{
    /// <summary>
    /// 数值微调控件(可指定最小值,最大值,步长,增长方式,如指数式、幂式等)
    /// </summary>
    [DefaultProperty("Value")]
    //[Designer(typeof(GWNumericDesigner))]
    [ToolboxData("<{0}:GWNumericUpDown runat=server></{0}:GWNumericUpDown>")]
    public class GWNumericUpDown : WebControl, INamingContainer
    {
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        //增加子控件
        private Button btn_add;
        //减少子控件
        private Button btn_sub;
        //文本框子控件
        private TextBox tb_Nummber;        #region 私有变量
        //初始值
        private int _value ;
        //步长
        private int _step ;
        //最大值
        private int _maxvalue ;
        //最小值
        private int _minvalue  ;
        //是否允许负值
        private bool _allownegative = true;
        #endregion        #region 属性
        /// <summary>
        /// 初始值
        /// </summary>
        [Bindable(true)]
        [Category("设定")]
        [Localizable(true)]
        [Description("控件的初始值")]
        [NotifyParentProperty(true)]
        public int Value
        {
            get { EnsureChildControls(); return _value; }
            set
            {
                EnsureChildControls();
                if (value >= this.MinValue && value <= this.MaxValue)
                    _value = value;
            }
        }
        /// <summary>
        /// 步长
        /// </summary>
        [Bindable(true)]
        [Category("设定")]
        [DefaultValue(1)]
        [Localizable(true)]
        [Description("设置每次点击增加或减少按钮时,变化的值")]
        [NotifyParentProperty(true)]
        public int Step
        {
            get { EnsureChildControls(); return _step; }
            set
            {
                EnsureChildControls();
                if (value >= 1)
                    _step = value;
            }
        }
        /// <summary>
        /// 最大值
        /// </summary>
        [Bindable(true)]
        [Category("设定")]
        [Localizable(true)]
        [Description("设置控件的最大值")]
        [NotifyParentProperty(true)]
        public int MaxValue
        {
            get { EnsureChildControls(); return _maxvalue; }
            set
            {
                EnsureChildControls();
                if (value >= this.MinValue)
                    _maxvalue = value;
                if (value < this.Value)
                    _maxvalue = this.Value;
            }
        }
        /// <summary>
        /// 控件值
        /// </summary>
        [Bindable(true)]
        [Category("设定")]
        [Localizable(true)]
        [Description("设置控件的最小值")]
        [NotifyParentProperty(true)]
        public int MinValue
        {
            get { EnsureChildControls(); return _minvalue; }
            set 
            { 
                EnsureChildControls();
                if (value <= this.MaxValue)
                {
                    _minvalue = value; 
                }
                if (value > this.Value)
                    this.Value = value;
            }
        }
        /// <summary>
        /// 是否允许负值
        /// </summary>
        [Bindable(true)]
        [Category("设定")]
        [Localizable(true)]
        [Description("设置是否允许负值")]
        [NotifyParentProperty(true)]
        public bool AllowNegative
        {
            get { EnsureChildControls(); return _allownegative; }
            set { EnsureChildControls(); _allownegative = value; }        }
        #endregion        #region  事件
        protected void btn_add_Click(object sender, EventArgs e)
        {
            if (this.MaxValue == 0)
            {
                this.Value =this.Value + this.Step;
            }
            else
            {
                if ((this.Value + this.Step) > this.MaxValue)
                {
                    return;
                }
                else
                {
                    this.Value = this.Value+ this.Step;
                }
            }
            this.tb_Nummber.Text = this.Value.ToString();
        }
        protected void btn_sub_Click(object sender, EventArgs e)
        {
            if (this.MinValue == 0)
            {
                if (AllowNegative)
                    this.Value = Convert.ToInt16(this.tb_Nummber.Text) - this.Step;
                else
                {
                    if ((this.Value - this.Step) < 0)
                    {
                        return;
                    }
                }
            }
            else
            {
                if ((this.Value - this.Step) < this.MinValue)
                {
                    return;
                }
                else
                {
                    this.Value =  this.Value - this.Step ;
                }
            }
            this.tb_Nummber.Text = this.Value.ToString();
        }
        #endregion        #region  创建子控件
        protected override void CreateChildControls()
        {
            Controls.Clear();
            btn_add = new Button();
            btn_add.ID = "btn_add";
            btn_add.Text = "+";
            btn_add.Width = 10;
            btn_add.Height = 15;
            btn_add.Click+=new EventHandler(btn_add_Click);
            btn_sub = new Button();
            btn_sub.ID = "btn_sub";
            btn_sub.Text = "-";
            btn_sub.Width = 10;
            btn_sub.Height = 15;
            btn_sub.Click +=new EventHandler(btn_sub_Click);
            tb_Nummber = new TextBox();
            tb_Nummber.ID = "tb_Nummber";
          
            tb_Nummber.Text = this.Value.ToString();
            tb_Nummber.Attributes["contentEditable"] = "false";
            tb_Nummber.Attributes.Add("style", "text-align:right");
            Controls.Add(btn_add);
            Controls.Add(btn_sub);
            Controls.Add(tb_Nummber);
        }
        #endregion        //#region  呈现控件
        protected override void Render(HtmlTextWriter writer)
        {
            AddAttributesToRender(writer);
            writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0", false);
            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.AddAttribute(HtmlTextWriterAttribute.Rowspan, "2");
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            //
            tb_Nummber.RenderControl(writer);
            writer.RenderEndTag();  // Td
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            //
            btn_add.RenderControl(writer);
            writer.RenderEndTag();  // Td
            writer.RenderEndTag();
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            //writer.RenderBeginTag(HtmlTextWriterTag.Td);
            ////
            //writer.RenderEndTag();  // Td
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            btn_sub.RenderControl(writer);
            writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Tr
            writer.RenderEndTag();  // Table
        }
        //#endregion
    }
}

解决方案 »

  1.   

    代码太长,没有开发环境,不高兴看了。
            //[Bindable(true)]
            [Category("设定")]
            //[Localizable(true)]
            [Description("设置控件的最小值")]
            //[NotifyParentProperty(true)]
    去掉这些看看。
      

  2.   

    VS的Form Designer有BUG。所以编写这种东西最好一步一步调试,从简单的开始,不然很难发觉哪里错了。
      

  3.   

    ==>1。控件放到页面上后无法正常显示。但更改某一属性后就能显示出来,但在源码与设计视图之间切换后就不好使了。可是在运行状态下可以正常显示。看看你的designer怎么写的?问题可能在这里。2。控件的VALUE等属性值为什么不更新。在属性设计器里就不好使,运行时点增加或减少按钮都没有反应。
    更新是指什么?在哪更新?运行时的问题你最好debug一下,检查一下你的逻辑是否有错误。
      

  4.   

    帮你看了一下,错误还真不少1。set Value的值没有作用
      因为在set Value的时候,子控件都已经创建好了,而tb_Nummber的Text是根据初始化时的Value值设置的,以后再修改Value的值,这个值不会反映到tb_Nummber中,自然从tb_Nummber这个文本框中看不出Value的变化。
      所以Value的set方法最后要加上:
      tb_Nummber.Text = _value.ToString();2。Value的值没有持久化保存
       你现在的Value值保存在实例变量_value中,每次页面PostBack时,这个变量始终都是初始值,所以Value的值不会依次递增/递减。所以Value属性要改成用ViewState,这样才能把Value值保存起来:
    public int Value
    {
    get { EnsureChildControls(); return ((int?)ViewState["_value"]).GetValueOrDefault(); }
    set
    {
    EnsureChildControls();
    if (value >= this.MinValue && value <= this.MaxValue)
    ViewState["_value"] = value;
    tb_Nummber.Text = _value.ToString();
    }
    }3. 为什么控件拖到设计视图上会报错
      因为设计视图显示控件外观时会调用你的Render方法,而你的Render方法里用了btn_add,btn_sub等,因为这时候还没有创建子控件(designer不会自动调用创建子控件过程),所以这些变量都是空的,设计视图上就会报错(引用了空值),如果这时候设置了某个属性,因为你在属性设置方法里都有EnsureChildControls,所以会创建子控件,再调用Render就不出错了。
      改掉这个错误的办法,在Render方法的开始处加上:
      if (this.DesignMode)
        EnsureChildControls();
    改完这些错误你的控件应该就可以运行了,测试的时候Step, MinValue, MaxValue都要设好初始值,否则不会看到效果。其实你的程序还有一些别的问题,不过不是致命性的,所以你先运行试试吧。