views:

627

answers:

2

I have a user control which uses objects as inner properties (some code is below).

I am having trouble with setting the attribute of the Step class programmatically, when set programmatically it is being lost across postback which would indicate something to do with Viewstate (?).

When setting the property of the Step class declaratively it's working fine.

Does anybody have any ideas of what this code be/what's causing it to lose the state across postback?

ASPX Page

    <uc1:StepControl ID="StepControl1" runat="server">
        <Step1 Title="1. Select your Products" Enabled="true">
            <Content>

                <div class="clearfix">
                    <div class="floatRight">
                        <asp:Button ID="btnGoToStep2" 
                        runat="server" 
                        Text="Next" 
                        CausesValidation="false" 
                        OnClick="btnGoToStep2_OnClick" />
                    </div>
                </div>

            </Content>
        </Step1>
        <Step2 Title="2. Select your Features">      
            <Content>

                <div class="clearfix">
                    <div class="floatLeft">
                        <asp:Button ID="btnBackToStep1" 
                        runat="server" 
                        Text="Back" 
                        CausesValidation="false" 
                        OnClick="btnBackToStep1_OnClick" />
                    </div>                    
                    <div class="floatRight">
                        <asp:Button ID="btnGoToStep3" 
                        runat="server" 
                        Text="Next" 
                        CausesValidation="false" 
                        OnClick="btnGoToStep3_OnClick" />
                    </div>
                </div>                    

            </Content>
        </Step2>                     
    </uc1:StepControl>

ASPX code behind

    protected void btnGoToStep2_OnClick(object sender, EventArgs e)
    {
        StepControl1.Step1.StatusText = "4 Products Selected";
    }

    protected void btnBackToStep1_OnClick(object sender, EventArgs e)
    {
        // StatusText (of Step1) gets lost at this point. 
    }

User control code behind

public partial class StepControl : System.Web.UI.UserControl
{
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [NotifyParentProperty(true)]
    public Step Step1 { get; set; }

    [PersistenceMode(PersistenceMode.InnerProperty)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [NotifyParentProperty(true)]
    public Step Step2 { get; set; }

    protected void Page_Init(object sender, EventArgs e)
    {
        AddSteps();
    }

    private void AddSteps() { }
}

[Serializable()]
[ParseChildren(true)]
[PersistChildren(false)]
public class Step
{
    [PersistenceMode(PersistenceMode.Attribute)]
    public string Title { get; set; }

    [PersistenceMode(PersistenceMode.Attribute)]
    public string Status { get; set; }

    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateInstance(TemplateInstance.Single)]
    [TemplateContainer(typeof(StepContentContainer))]
    public ITemplate Content { get; set; }

    public class StepContentContainer : Control, INamingContainer { }
}
A: 

It might have something to do with the order of the creation of your controls in the page. If after a postback, the controls are not created in the same order as for the first load of the page, then retreiving the viewstate willl not work for those controls.

How do you set the attribute of step programmatically?

Yoann
@yoannr: I've updated the question with some additional code.
Robert W
Didn't find a solution, sorry! if you find anything , keep us informed.. ;)
Yoann
+1  A: 

I think the string you set never makes it to the ViewState. I am a bit short of terminology here (read: I do not know the terminology) but I think your attribute [PersistenceMode(PersistenceMode.Attribute)] only tells ASP.NET it should look for an attribute called "Status" in the markup (ASPX-file) and if it finds one, set the property Status to its value (actually I am wondering where exactly it is put in your example?). It does not tell anybody to put something into ViewState though.

If you would define your property Status along these lines

[PersistenceMode(PersistenceMode.Attribute)]
public string Status
    {
        get
        {
            object o = ViewState["Status"];
            if(o != null) {
                return (string)o;
            }
            return string.Empty;
        }
        set
        {
            ViewState["Status"] = value;
        }
    }

you should be better off.

For the rest of it I am not sure if you have to call TrackViewState() in UserControls or even override SaveViewState and LoadViewState but I do not think so. If this would be the case the following links might help:

scherand