Question

I'm reading through some MSDN example code on Composite controls and finding that there is one thing I don't understand. Using the code here I've created the LabelTextBox control in my project and added it to a page. If I enter a new value into the textbox in the control, the button click event has the old value when I post back to the server. If I allow the page to continue processing the page finishes reloading with the new value though. Is this a poor example or am I missing something? Shouldn't the changed value be loaded into the control before the button event fires?

The composite control code:

public class LabelTextBox : WebControl, INamingContainer
{
    public string Text
    {
        get
        {
            object o = ViewState["Text"];
            if (o == null)
                return String.Empty;
            return (string)o;
        }
        set { ViewState["Text"] = value; }
    }
    public string Title
    {
        get
        {
            object o = ViewState["Title"];
            if (o == null)
                return String.Empty;
            return (string)o;
        }
        set { ViewState["Title"] = value; }
    }
    protected override void CreateChildControls()
    {
        Controls.Clear();
        CreateControlHierarchy();
        ClearChildViewState();
    }
    protected virtual void CreateControlHierarchy()
    {
        TextBox t = new TextBox();
        Label l = new Label();
        t.Text = Text;
        l.Text = Title;
        Controls.Add(l);
        Controls.Add(t);
    }
}

I've tried creating the control declaratively and programatically with no change in the results. The programatic creation code:

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Form.Controls.Add(new LiteralControl("<br /><br />"));

        TextBox tb = new TextBox();
        tb.Text = "before";
        Form.Controls.Add(tb);

        Form.Controls.Add(new LiteralControl("<br /><br />"));

        LabelTextBox ltb = new LabelTextBox();
        ltb.Title = "title";
        ltb.Text = "before";
        Form.Controls.Add(ltb);


    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        foreach( var c in Form.Controls)
        {
            var control = c as TextBox;
            if (control != null) 
            {
                System.Diagnostics.Debug.WriteLine(String.Format("TextBox: {0}", control.Text)); 
            }
            else
            {
                var control2 = c as LabelTextBox;
                if (control2 != null)
                {
                    System.Diagnostics.Debug.WriteLine(String.Format("LabelTextBox: {0}", control2.Text));
                }
            }
        }
    }
}
Was it helpful?

Solution

I think the problem with your first approach is that you are keeping the values in the parent's Viewstate, but never reading the values back in from the children. Try something like:

public class LabelTextBox : WebControl, INamingContainer
{
    private Label _Label     = new Label() { ID="uxLbl" };
    private TextBox _TextBox = new TextBox() { ID="uxTb" };

    public string Text
    {
        get { return _TextBox.Text; }
        set { _TextBox.Text = value; }
    }
    public string Title
    {
        get { return _Label.Text; }
        set { _Label.Text = value; }
    }
    protected override void CreateChildControls()
    {
        Controls.Clear();
        CreateControlHierarchy();
    }
    protected virtual void CreateControlHierarchy()
    {
        Controls.Add(_Label);
        Controls.Add(_TextBox);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top