Answered by:
CompositeControl and order of LoadPostData

Question
-
User-1643923816 posted
Hello Guys,
I have a kind of philosophical question about control creation.
Let's imagine you have the following scenario :
- A CompositeControl composed of a TextBox (let's name it SuperTextBox)
- for a more realistic scenario, let's imagine this is a control including validation, AJAX stuff like AjaxControlToolkit controls, ...
- Another CompositeControl composed of several "SuperTextBox" (let's name is MyContainer)
So typically, here is how my SuperTextBox would look like :
public class SuperTextBox : CompositeControl { private TextBox txt; public string Text { get { this.EnsureChildControls(); return this.txt.Text + "Super"; } set { this.EnsureChildControls(); this.txt.Text = value + "Super"; } } protected override void CreateChildControls() { base.CreateChildControls(); this.txt = new TextBox() { ID = "txt" }; this.Controls.Add(this.txt); } }
What do you think of this implementation ? Here, I do not want to implement IPostBackDataHandler (well at least I do not think it's necessary) as all my loading stuff is done by the internal TextBox. Do you agree with me so far ?
So what I want to do now is to create the MyContainer control which will be the editor of a simple class. Let's take for example :
[Serializable]
public class MyObject { public string Name { get; set; } public string FirstName { get; set; } }
So my feeling is that the MyContainer control should hold a property storing in the view state this object, and that this one should implement IPostBackDataHandler to fill it (if necessary).
So I would suggest something like :
public class MyContainer : CompositeControl, IPostBackDataHandler { private SuperTextBox txtName; private SuperTextBox txtFirstName; public MyObject Object { get { return (MyObject)ViewState["Object"]; } set { ViewState["Object"] = value; } } protected override void CreateChildControls() { base.CreateChildControls(); this.txtName = new SuperTextBox() { ID = "txtName" }; this.Controls.Add(this.txtName); this.txtFirstName = new SuperTextBox() { ID = "txtFirstName" }; this.Controls.Add(this.txtFirstName); } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); this.Page.RegisterRequiresPostBack(this); this.txtName.Text = this.Object.Name; this.txtFirstName.Text = this.Object.FirstName; } #region IPostBackDataHandler Members bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { /* We want here to update the property with the newly posted value * Each control having its own mechanism for loading its postdata, we shall rely here * on the child control's properties */ this.EnsureChildControls(); this.Object.Name = this.txtName.Text; this.Object.FirstName = this.txtFirstName.Text; return true; } void IPostBackDataHandler.RaisePostDataChangedEvent() { //No Event to raise } #endregion }
Here as I want to update my object, I implement the IPostBackDataHandler and I load my object with the new values. As my child control are already responsible of loading / validating / transforming their data, I do not want to load from postCollection, but really from my child controls.
That's why I do "EnsureChildControls".
However, we have no control - as far as I know - about the order into which the LoadPostData will be called. So there is a risk that when the MyContainer's LoadPostData method will be called, the TextBox's LoadPostData will not be called yet.
As a result, I do not have the value.
My question is "simple". What would you do ? Just some hints about my "specifications"
- There are many validation / transformation / computation done in my SuperTextBox and so it should be responsible of loading its data from the post collection (do you agree ?)
- I do not really want to do a DataboundControl (am I wrong ?) as they work as "fire and forget" and thus I should handle many events to get back the updated values
- The solution I propose will increase the view state size but this is acceptable in my scenario where I will edit almost (99%) all the fields of MyObject via MyContainer.
What do you think ?
Tuesday, December 15, 2009 11:50 AM - A CompositeControl composed of a TextBox (let's name it SuperTextBox)
Answers
-
User-1635004338 posted
Hi JarodTWeiss,
Have a look at these possible solutions:
http://forums.asp.net/t/1160413.aspx
http://www.andypotts.com/Blog/2009/02/19/CompositeControlDidNotCallLoadPostData.aspx
http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_22524970.html
Thanks,
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Thursday, December 17, 2009 10:26 PM