希望了解的人帮我解决这个问题,困扰比较久了,代码如下
简单的一个控件,里面有一个label,有一个外部方法可以改变这个label的值,问题是,label的值被改变后,页面上任何一个提交动作,都会让label的text变成空,虽然知道load和save viewstate的逻辑,但对于这样的child control,怎么保存其状态?希望高人详细解释之,能解我疑惑,要多少分都好商量。 public class Class1 : CompositeControl
    {
        Label label = new Label();        protected override void CreateChildControls()
        {
            label.ID = "xxx";
            Controls.Add(label);
            base.CreateChildControls();
        }        public void ChangeText(string str)
        {
            label.Text = str;
        }
        protected override void Render(HtmlTextWriter writer)
        {
            label.RenderControl(writer);
            //base.Render(writer);
        }        protected override object SaveViewState()
        {
            return base.SaveViewState();
        }        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState();
        }
    }

解决方案 »

  1.   

    最简单的方法,使用session。把值保存的session中。
    在控件加载时改变这个label的值 = session[key]
    或者在创建label的时候直接设置label数据绑定 session[key]
      

  2.   

    当页面提交的时候这个控件的创建类就会把label对象重置了呀,是否可用session保存状态呢?在构造函数里判断session是否为null,接下来
      

  3.   

    各位,我不是简单说要保存这么一个label的值的问题,是关于asp.net控件视图的原理问题,大家想想grid view这么大一个控件,里面有多少个子控件,用session是不可能的,所以我郁闷了。
      

  4.   

     public class Class1 : CompositeControl
        {
            Label label = new Label();        protected override void CreateChildControls()
            {
                label.ID = "xxx";
                Controls.Add(label);
                base.CreateChildControls();
            }        public void ChangeText(string str)
            {
                label.Text = str;
            }
            protected override void Render(HtmlTextWriter writer)
            {
                label.RenderControl(writer);
                //base.Render(writer); 
            }        protected override object SaveViewState()
            {
                return base.SaveViewState();
            }        //protected override void LoadViewState(object savedState)
            //{
            //    base.LoadViewState();
            //}        protected override void LoadControlState(object savedState)
            {
                base.LoadControlState(savedState);
            }
        }
      

  5.   

    重写LoadViewState,SaveViewState,TrackViewState这三个方法
    你光有前两个不行http://www.cnblogs.com/Clingingboy/archive/2006/09/19/507864.html
    把这个看明白了.
      

  6.   

    关键在于这几句话:
    Label label = new Label();         protected override void CreateChildControls() 
            { 
                label.ID = "xxx"; 
                Controls.Add(label); 
                base.CreateChildControls(); 
            }         public void ChangeText(string str) 
            { 
                label.Text = str; 
            }
      

  7.   

    回发提交时  肯定又执行 :Label label = new Label(); 这时肯定为空了!
    应该定义一个属性 ProText 存在 viewstate 里面
      

  8.   

    你试试吧.不行了再说.我随手写的.没有试
    public class Class1 : CompositeControl 
        { 
            Label label = new Label(); 
            protected override void CreateChildControls() 
            { 
                label.ID = "xxx"; 
                label.Text = LblText;
                Controls.Add(label); 
                base.CreateChildControls(); 
            } 
            [
            BrowsableAttribute(true),
            Bindable(true),
            Category("Appearance"),
            DefaultValue("xxxxx"),
            Localizable(true),
            Description("The text to be shown on the label"),
            ]
            public string LblText
            {
                get
                {
                    //EnsureChildControls();
                    return label.Text == string.Empty ? "xxx" : label.Text;
                }
                set
                {
                    //EnsureChildControls();
                    label.Text = value;
                }
            }
            public void ChangeText(string str) 
            { 
                LblText = str; 
            } 
            protected override void Render(HtmlTextWriter writer) 
            { 
                label.RenderControl(writer); 
                //base.Render(writer); 
            } 
        }
      

  9.   

            public void ChangeText(string str)
            {
                label.Text = str;
            }
    -----------
    不是这么干地        public void ChangeText(string str)
            {
                stateview["text"] = str;
            }
            protected override void Render(HtmlTextWriter writer) 
            { 
                label.text=stateview["text"]!=null?stateview["text"].tostring():string.empty;
                label.RenderControl(writer); 
                //base.Render(writer); 
            } 
      

  10.   

    public class Class1 : CompositeControl 
        { 
            Label label = null;        protected override void CreateChildControls() 
            { 
                label =new lable();
                label.ID = "xxx"; 
                Controls.Add(label); 
                base.CreateChildControls(); 
            }         public void ChangeText(string str) 
            { 
                label.Text = str; 
            } 
            protected override void Render(HtmlTextWriter writer) 
            { 
                label.RenderControl(writer); 
                //base.Render(writer); 
            }     }
    这样应该可以了
      

  11.   

    public class Class1 : CompositeControl 
        { 
             Label label;        protected override void CreateChildControls()
            {
                label = new Label();
                label.ID = "xxx";
                Controls.Add(label);
                base.CreateChildControls();
            }        public xx()
            {
                EnsureChildControls();
            }
            public void ChangeText(string str)
            {
                EnsureChildControls();
                label.Text = str;
            }        protected override void Render(HtmlTextWriter writer)
            {
                label.RenderControl(writer);
                //base.Render(writer); 
            }        protected override object SaveViewState()
            {
                return base.SaveViewState();
            }        protected override void LoadControlState(object savedState)
            {
                base.LoadControlState(savedState);
            }
        } 
    这样应该可以了
      

  12.   

    也不是你那样干的
    人家是要设置子控件label 的text 不是设置 父控件的 stateview 
      

  13.   

    最新答案
     public void ChangeText(string str)
            {
                EnsureChildControls();
                label.Text = str;
            }
    在那个ChangeText 方法前+个EnsureChildControls()就可以了
      

  14.   

    请问下有谁对父控件中所有子控件状态维持比较熟悉,在我的印象里面,page中的所有control都应该是在控件树里面,父控件里面也有自己的小控件树,那么,怎么样让所有的控件的状态都得以维护呢,在本问题里面,我只写了一个小label,但如果是一个大控件里面有上百个小控件,如gridview一样,那么怎么实现状态维持,请明白的人来详细说一说.
      

  15.   


    重写LoadViewState,SaveViewState,TrackViewState这三个方法,我上面不是告诉你了吗,要自定义状态视图.
    也给你参考文章了.protected override void LoadViewState(object savedState)
            {
                if (savedState == null)
                {
                    base.LoadViewState(null);
                    return;
                }
                else
                {
                    Triplet t = savedState as Triplet;                if (t != null)
                    {
                        base.LoadViewState(baseState);                    if ((t.Second) != null)
                        {
                            ((IStateManager)ButtonStyle).LoadViewState(buttonStyleState);
                        }                    if ((t.Third) != null)
                        {
                            ((IStateManager)TextBoxStyle).LoadViewState(textBoxStyleState);
                        }
                        if (labelStyleState != null)
                        {
                            ((IStateManager)(_labelStyle)).LoadViewState(labelStyleState);
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Invalid view state .");
                    }
                }
            }        protected override object SaveViewState()
            {
                baseState = base.SaveViewState();
                buttonStyleState = null;
                textBoxStyleState = null;
                labelStyleState = null;
                if (_buttonStyle != null)
                {
                    buttonStyleState =
                        ((IStateManager)_buttonStyle).SaveViewState();
                }            if (_textBoxStyle != null)
                {
                    textBoxStyleState =
                        ((IStateManager)_textBoxStyle).SaveViewState();
                }
                if (_labelStyle != null)
                {
                    labelStyleState = ((IStateManager)_labelStyle).SaveViewState();
                }
                return new Triplet(baseState,
                    buttonStyleState, textBoxStyleState);        }        protected override void TrackViewState()
            {
                base.TrackViewState();
                if (_buttonStyle != null)
                {
                    ((IStateManager)_buttonStyle).TrackViewState();
                }
                if (_textBoxStyle != null)
                {
                    ((IStateManager)_textBoxStyle).TrackViewState();
                }
                if (_labelStyle != null)
                {
                    ((IStateManager)_labelStyle).TrackViewState();
                }
            }
      

  16.   


    楼上的哥们,谢谢你给的代码,但是如果是子control本身,是不从IStateManager继承来的,那么怎么让子control也进行状态跟踪,我用了woaixueyu 的代码, EnsureChildControls()调用后确实解决了问题,但我不知道原理,楼上哥们知道吗,如果知道跟我说说,感激不尽,有需要我可以另外开贴给分.多谢大家了
      

  17.   

    EnsureChildControls()
    该方法首先检查 ChildControlsCreated 属性的当前值。如果此值为假,则调用 CreateChildControls 方法。
      

  18.   

    楼上哥们,谢谢你了,不知道可否加我msn一下,本贴我结帖给分先,我的msn是: [email protected].希望能跟你多交流,谢谢.
      

  19.   

     protected override void CreateChildControls() 
            { 
                label.ID = "xxx"; 
                label.Text = LblText;
                Controls.Add(label); 
                base.CreateChildControls(); 
            } 
    改成
    protected void Page_Load(object sender, EventArgs e)
    {
                   
        // TrackViewState()方法将被触发去跟踪这个label的状态,所以其状态将被保持
        Controls.Add(label); //要写在添加数据的前面    if (!IsPostBack)
        {
           label.ID = "xxx"; 
           label.Text = LblText;
        }
    }
      

  20.   

    CreateChildControls事件是触发在lode事件之后才能触发
    保存状态要在初始化方法之后的LoadViewState()和LoadPostData() 事件中保存
    到这里也许有人要写到Page_Init()事件中 
    //Pre_Init()方法里重新创建控件(它们发生在LoadViewState和LoadPostData之前),这样就可以在下一个事件里获得控件的值  
    但是如果把代码写到Page_Init()事件里的话,将不能得到用户在ChildControl里输入的值。原因就在于这是Page_Init()事件,控件的值被初始化为它们设计时的默认值,而不会得到用户输入的值
    如果要在这里访问到用户输入的值话只有一个办法,就是从POST数据中取值
    如果你在Page_Load事件里创建一个动态控件,并把它添加到PlaceHolder或Panel里(要打开view state),那么动态控件将会维持它的状态,即使它不是在Page_Init()中创建的
    因为 控件一旦被添加到页的控件树里,TrackViewState()方法就负责跟踪其状态。只要控件被添加到控件树里,这个方法就会被自动的触发。因为这个原因,对控件的任何修改(如添加item之类的)都应该在动态控件被添加到页的控件树之后来做,否则其状态将丢失
    代码 看上面吧