首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • ASP.Net复合控件子控件状态保持的问题,高手来,先贴110,不够再加。 [已结帖,结帖人:leonbingo]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leonbingo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-11-18 23:48:36 楼主
    希望了解的人帮我解决这个问题,困扰比较久了,代码如下
    简单的一个控件,里面有一个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();
            }
        }
    110  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fiendloop
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-18 23:59:371楼 得分:0
    最简单的方法,使用session。把值保存的session中。
    在控件加载时改变这个label的值 = session[key]
    或者在创建label的时候直接设置label数据绑定 session[key]
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dingjian2008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 00:04:332楼 得分:0
    当页面提交的时候这个控件的创建类就会把label对象重置了呀,是否可用session保存状态呢?在构造函数里判断session是否为null,接下来。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leonbingo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 00:10:483楼 得分:0
    各位,我不是简单说要保存这么一个label的值的问题,是关于asp.net控件视图的原理问题,大家想想grid view这么大一个控件,里面有多少个子控件,用session是不可能的,所以我郁闷了。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • oec2003
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 00:15:274楼 得分:0
    C# code
    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); } }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leonbingo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 00:23:275楼 得分:0
    楼上的哥们,经过尝试,这个解决方案无效啊,如果你明白,希望你帮忙测试一下,给我个详细解释哦,谢谢了啊。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leonbingo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 08:08:376楼 得分:0
    自顶
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lovehongyun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 09:01:027楼 得分:0
    重写LoadViewState,SaveViewState,TrackViewState这三个方法
    你光有前两个不行

    http://www.cnblogs.com/Clingingboy/archive/2006/09/19/507864.html
    把这个看明白了.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • iyori
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 09:07:268楼 得分:0
    关键在于这几句话:
    Label label = new Label();

            protected override void CreateChildControls()
            {
                label.ID = "xxx";
                Controls.Add(label);
                base.CreateChildControls();
            }

            public void ChangeText(string str)
            {
                label.Text = str;
            }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • iyori
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 09:08:359楼 得分:0
    回发提交时  肯定又执行 :Label label = new Label(); 这时肯定为空了!
    应该定义一个属性 ProText 存在 viewstate 里面
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lovehongyun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 09:11:5010楼 得分:0
    你试试吧.不行了再说.我随手写的.没有试
    C# code
    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); } }

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • anncesky
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 09:49:5711楼 得分:0
            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);
            }

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • woaixueyu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 09:51:5112楼 得分:0
    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);
            }

        }
    这样应该可以了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • woaixueyu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 10:03:3713楼 得分:60
    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);
            }
        }
    这样应该可以了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • woaixueyu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 10:06:4414楼 得分:0
    引用 11 楼 anncesky 的回复:
            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…

    也不是你那样干的
    人家是要设置子控件label 的text 不是设置 父控件的 stateview
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • flyerwing
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 10:50:4315楼 得分:0
    学习下了!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • woaixueyu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 11:10:4216楼 得分:0
    最新答案
    public void ChangeText(string str)
            {
                EnsureChildControls();
                label.Text = str;
            }
    在那个ChangeText 方法前+个EnsureChildControls()就可以了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leonbingo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 12:53:2417楼 得分:0
    请问下有谁对父控件中所有子控件状态维持比较熟悉,在我的印象里面,page中的所有control都应该是在控件树里面,父控件里面也有自己的小控件树,那么,怎么样让所有的控件的状态都得以维护呢,在本问题里面,我只写了一个小label,但如果是一个大控件里面有上百个小控件,如gridview一样,那么怎么实现状态维持,请明白的人来详细说一说.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lovehongyun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 13:04:3218楼 得分:0
    引用 17 楼 leonbingo 的回复:
    请问下有谁对父控件中所有子控件状态维持比较熟悉,在我的印象里面,page中的所有control都应该是在控件树里面,父控件里面也有自己的小控件树,那么,怎么样让所有的控件的状态都得以维护呢,在本问题里面,我只写了一个小label,但如果是一个大控件里面有上百个小控件,如gridview一样,那么怎么实现状态维持,请明白的人来详细说一说.


    重写LoadViewState,SaveViewState,TrackViewState这三个方法,我上面不是告诉你了吗,要自定义状态视图.
    也给你参考文章了.

    C# code
    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(); } }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leonbingo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 13:25:4819楼 得分:0
    引用 16 楼 woaixueyu 的回复:
    最新答案
    public void ChangeText(string str)
            {
                EnsureChildControls();
                label.Text = str;
            }
    在那个ChangeText 方法前+个EnsureChildControls()就可以了


    楼上的哥们,谢谢你给的代码,但是如果是子control本身,是不从IStateManager继承来的,那么怎么让子control也进行状态跟踪,我用了woaixueyu 的代码, EnsureChildControls()调用后确实解决了问题,但我不知道原理,楼上哥们知道吗,如果知道跟我说说,感激不尽,有需要我可以另外开贴给分.多谢大家了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lovehongyun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 13:37:4720楼 得分:50
    EnsureChildControls()
    该方法首先检查 ChildControlsCreated 属性的当前值。如果此值为假,则调用 CreateChildControls 方法。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leonbingo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-19 13:43:1421楼 得分:0
    楼上哥们,谢谢你了,不知道可否加我msn一下,本贴我结帖给分先,我的msn是: S_leonbingo@hotmail.com.希望能跟你多交流,谢谢.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • peiyanfei2008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 13:39:1022楼 得分:0
    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;
        }
    }

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • peiyanfei2008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 13:47:4123楼 得分:0
    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之类的)都应该在动态控件被添加到页的控件树之后来做,否则其状态将丢失
    代码 看上面吧 

    修改 删除 举报 引用 回复