views:

1003

answers:

3

I have a very simple usercontrol, basically a textbox and a label, whose purpose is to toggle between one another. The control is bound during the page's Page_Load event. On the UserControl's Page_Load event, I call the Toggle() function, which shows or hides the appropriate control and sets its text based on a boolean Editable property and string Text property, respectively.

Here's my Toggle() method (remember Editable and Text are public properties):

Public Sub Toggle()
 If Editable Then
  txtText.Visible = True
  lblText.Visible = False
  txtText.Text = Text
  txtText.CssClass = TextboxCSSClass
 Else
  txtText.Visible = False
  lblText.Visible = True
  lblText.Text = Text
  lblText.CssClass = LabelCSSClass
 End If
End Sub

My problem is also simple: when a button on the page calls the control's Toggle() method, the toggling works fine, but the text disappears! I've tried this with a normal unbound textbox next to it, and the textbox maintains its text value just fine. Is there something I'm missing?

Thanks for your help in advance.

A: 

When you set the visible property of a control to False, it will not be rendered in Html thus it can't carry state between pages. Instead consider using MultiView control

Ender
The control itself is never set to visible=false, just the controls inside it. The control's Text property SHOULD maintain its value through postbacks, right?
Jason
No the textbox will not maintain state through postbacks since you set its visible to false. what you need to do in your control is, create a MultiView and create two views in it. in first view you will put the textbox and in the second label. Then you need to change ActiveViewIndex of MV if Editabl
Ender
Right, but I set its text property after I make it visible again. The USERCONTROL's Text property should persist. I understand the Textbox's Text property INSIDE the UserControl should NOT persist, but the UserControl's should. In my opinion, at least :) Right?
Jason
Ender - I tried your MV solution and I am having the same problem. The UserControl's Text property just does not hold on to its value through postbacks. It doesn't make any sense :(
Jason
Did you disable the ViewState somewhere in the control chain? search for EnableViewState="False" in the project
Ender
No.. I haven't touched the ViewState :\ I actually DID put EnableViewState="True" in my .ascx control to see if that would help before you suggested it. No dice.
Jason
If you want to upload the piece of code I'd be happy to look
Ender
@Ender the textbox does mantains the state accross postback when visible set to false - it wouldn't mantain it if the textbox is never on the page hierarchy or if the viewstate above it is disabled ... posted an answer to what seems to be the specific problem.
eglasius
A: 

Update: More info regarding the comments.

If you have the viewstate disabled, and you set the text for textboxes, the text is the one in the input control. This can affect you in the uncommon scenario when you are trying to know if a given textbox's value changed.

The above is different for a label, since it isn't an input control. With the viewstate disabled, if you don't set the text on every request, it will show the initial value (try it out). The viewstate is what automatically allows to keep the information accross postbacks for the controls.

Just as it happens with the label, it happens with your user control. If you change the setter so it sets both controls texts directly, it will keep the value in the inner controls if you are using the viewstate. If you turn it off, it would behave different for the label than for the textbox.

Also note, that turning off the viewstate, would also affect your Visible configuration. I turn the viewstate off a lot, but you might have an scenario where you really want to keep the controls information accross postbacks. When turning off the viewstate, you need to make sure to always configure the controls, not only when !IsPostBack.

Note that if you keep track of what is supposed to be Visible and the text in your code, then you could turn off the inner control's viewstate (assuming you are not assigning any other property to them).


Initial answer:

You are assigning the current value of the Text property to the label/textbox. If you didn't set the value in the current request, then it has its default value, thus you are getting the empty text.

You can save the value in the viewstate as (c# syntax):

public string Text
{
   get
   {
      return (string) ViewState["MyText"];
   }
   set
   {
      ViewState["MyText"] = value;
   }
}

Ps. this isn't the only way to do it. If the toggle didn't set the text, but you did it on the setter to both controls, then they would keep the values (as long as you assign the Text property of the user control after viewstate is being tracked, like in page Load).

eglasius
so the only way to do this is by using viewstate? i would like to use this control for profile viewing/editing purposes... would that not bog up my app? Why doesn't the UserControl's Text's Set work across postbacks?
Jason
sorry, i missed your text after your code sample. I set the Text property on Page_Load if Not isPostBack, just like any other control (textboxes, etc). Are user controls special somehow?
Jason
@Jason added an update explaining more about it.
eglasius
thanks freddy... i got it all worked out now and i've added some additional awesome features to it :)
Jason
@Jason accepted answer are always welcomed :)
eglasius
@Freddy - I would accept your answer, but I feel like it would be misleading since I didn't actually use your ViewState solution. You were definitely instrumental in me figuring out what was wrong though. So I send you karma points instead (much more useful anyways :) )! Thanks again!
Jason
@Jason lol, karma points are great as well :), btw updated the answer so the update is the first thing that appears. As you already solved it, then mark your own answer as accepted :)
eglasius
A: 

I figured it out! I apologize for being dumb. Here's what I was doing wrong: My Get/Set for the Text Property was being stored in a private member. This means that when updates were made to the text, it didn't know, since it wasn't connected to the textbox. Instead, I did the following:

Public Property Text() As String
 Get
  Return txtText.Text
 End Get
 Set(ByVal value As String)
  txtText.Text = value
 End Set
End Property

and in my Page_Load event:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 If Not IsPostBack Then
  lblText.Text = Text
  Toggle()
 End If
End Sub

and now it works fine! Thanks to those that put me down the right path! :)

Jason