Custom Control problem.

D

David

Hi all,

I am not quite sure how to phrase the subject, so apologies.

I am writing a custom control. It is using a textbox. I create the text box,
but cannot read the contents of it later.

Here is my code...

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;

namespace MyProjectControls
{
/// <summary>
/// Summary description for WebCustomControl1.
/// </summary>
[DefaultProperty("Text"),
ToolboxData("<{0}:WebCustomControl1
runat=server></{0}:WebCustomControl1>")]
public class HTMLPlaceHolder : System.Web.UI.WebControls.WebControl
{

private System.Web.UI.WebControls.TextBox tb = new TextBox();


private string text;
private string _CurrentViewMode = "display";

[Bindable(true),
Category("Appearance"),
DefaultValue("")]
public string Text
{
get
{
return text;
}

set
{
text = value;
}
}

public string CurrentViewMode
{
get
{
return _CurrentViewMode.ToLower();
}

set
{
_CurrentViewMode = value.ToLower();
}
}

/// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void Render(HtmlTextWriter output)
{

RenderContents(output);

}


protected override void OnPreRender(EventArgs e)
{
System.Web.UI.Page MyPage = this.Page as System.Web.UI.Page;

CurrentViewMode = MyPage.PageState;

Text = "This is purely test text"

if (MyPage.AllowSave)
{
SavePlaceholder();
}

switch (CurrentViewMode)
{
case "edit" :
AuthoringPlaceholder();
break;
case "display" :
DisplayPlaceholder();
break;
case "design" :
DesignPlaceholder();
break;
default:
DisplayPlaceholder();
break;
}


base.OnPreRender (e);
}

protected void DesignPlaceholder()
{
}

protected void AuthoringPlaceholder()
{
//TextBox tb = new TextBox();

//this.tb = new TextBox();
this.tb.ID = this.ID;
this.tb.TextMode = TextBoxMode.MultiLine;
this.tb.Text = Text;
this.tb.Columns = 40;
this.tb.Rows = 15;

Controls.Add(this.tb);

}

protected void DisplayPlaceholder()
{
LiteralControl lit = new LiteralControl("<div>" + Text + "</div>");
Controls.Add(lit);
}

protected void SavePlaceholder()
{
System.Web.HttpContext.Current.Response.Write(this.tb.Text);
}

}
}


In the SavePlaceHolder, I want to be able to display what is written in the
text box. (Actually, I want to save it, but to display it will show that
something is happening).

However, this.tb.Text has nothing in it in the SavePlaceholder.

How can I ensure that what is coming back when the page is submitted is
actually there?

Thanks.

Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
T

tdotnet

It's been a while since I've done one of these, but glancing through
the code, I could be just missing it, but I could not find where your
Text property sets the .Text property of the TextBox. And where or how
do you restore the value to your text field string on a postback?

-Tyler
http://www.netbrick.net - The .NET Developer Search Engine
Hi all,

I am not quite sure how to phrase the subject, so apologies.

I am writing a custom control. It is using a textbox. I create the text box,
but cannot read the contents of it later.

Here is my code...

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;

namespace MyProjectControls
{
/// <summary>
/// Summary description for WebCustomControl1.
/// </summary>
[DefaultProperty("Text"),
ToolboxData("<{0}:WebCustomControl1
runat=server></{0}:WebCustomControl1>")]
public class HTMLPlaceHolder : System.Web.UI.WebControls.WebControl
{

private System.Web.UI.WebControls.TextBox tb = new TextBox();


private string text;
private string _CurrentViewMode = "display";

[Bindable(true),
Category("Appearance"),
DefaultValue("")]
public string Text
{
get
{
return text;
}

set
{
text = value;
}
}

public string CurrentViewMode
{
get
{
return _CurrentViewMode.ToLower();
}

set
{
_CurrentViewMode = value.ToLower();
}
}

/// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void Render(HtmlTextWriter output)
{

RenderContents(output);

}


protected override void OnPreRender(EventArgs e)
{
System.Web.UI.Page MyPage = this.Page as System.Web.UI.Page;

CurrentViewMode = MyPage.PageState;

Text = "This is purely test text"

if (MyPage.AllowSave)
{
SavePlaceholder();
}

switch (CurrentViewMode)
{
case "edit" :
AuthoringPlaceholder();
break;
case "display" :
DisplayPlaceholder();
break;
case "design" :
DesignPlaceholder();
break;
default:
DisplayPlaceholder();
break;
}


base.OnPreRender (e);
}

protected void DesignPlaceholder()
{
}

protected void AuthoringPlaceholder()
{
//TextBox tb = new TextBox();

//this.tb = new TextBox();
this.tb.ID = this.ID;
this.tb.TextMode = TextBoxMode.MultiLine;
this.tb.Text = Text;
this.tb.Columns = 40;
this.tb.Rows = 15;

Controls.Add(this.tb);

}

protected void DisplayPlaceholder()
{
LiteralControl lit = new LiteralControl("<div>" + Text + "</div>");
Controls.Add(lit);
}

protected void SavePlaceholder()
{
System.Web.HttpContext.Current.Response.Write(this.tb.Text);
}

}
}


In the SavePlaceHolder, I want to be able to display what is written in the
text box. (Actually, I want to save it, but to display it will show that
something is happening).

However, this.tb.Text has nothing in it in the SavePlaceholder.

How can I ensure that what is coming back when the page is submitted is
actually there?

Thanks.

Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
M

Michael Hamrah

I think the problem you have is that you're not loading the contents of
the control tree properly. I don't think .NET can find the Textbox
control when a Postback happens so it can't properly set the textbox
text property. This is because you're only adding the textbox in the
PreRender event if the user is in edit mode.

You want to sure ensure that all controls sent to the client are loaded
again in the init event during a postback. THis allow .NET to properly
map form objects to .NET controls. You can try either 1) Always
loading the textbox but setting the visible property to true or false,
2) Add a marker that will tell the control to load the Textbox in the
Init event if it was sent out during the Init event. 3) Explicitly
setting the text property of the Textbox by implementing the
IPostBackDataHandler interface.
 
D

David

Hi,

Thank you both (tdotnet and Michael), however I am still having problems...
It may be a combination of both answers.

I have written an OnInit

protected override void OnInit(EventArgs e)
{
//tb.ID = this.ID;
tb.TextMode = TextBoxMode.MultiLine;
//this.tb.Text = Text;
tb.Columns = 40;
tb.Rows = 15;

Controls.Add(tb);
base.OnInit (e);
}

(Note, the Text property has been remarked, as that can only really be
loaded in the OnPreRender).

This seems to prepare the textbox but on the postback, when I am trying to
read it, there is nothing. How do I ensure that there is text in the
postback?

(I pre-load the text box in pre-render, I wish to be able to change the
contents and I want to see what is in the text boxes when it comes back)

I have never used the IPostBackDataHandler. Given what I have written above,
does it look like this is what I need? If so, can you show me an example?

Thanks.

Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
M

Michael Hamrah

The IPostBackDataHandler returns a boolean value if the data has
changed in the control. THis is so it can raise a data changed event.

I wrote the following code below which doesn't use the
IPostBackDataHandler (it relies on the textbox data handler, but it may
not fit your needs in the long run.

Anyway, the trick is to leverage the CreateChildControls function.
This function gets called anytime .NET needs the control to be in a
valid state- essentially during a postback after the init event and
before it gets rendered.

public class HTMLPlaceholder : CompositeControl
{
private TextBox tb = new TextBox();

private string _text;
private string _viewMode;

public string ViewMode
{
get { return (ViewState["ViewMode"] == null) ? "default" :
ViewState["ViewMode"].ToString(); }
set { ViewState["ViewMode"] = value; }
}
public string Text
{
get { return _text; }
set { _text = value; }
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
this.Text = tb.Text;
base.OnLoad(e);
}
protected override void OnPreRender(EventArgs e)
{

CreateChildControls();
base.OnPreRender(e);
}
protected override void CreateChildControls()
{
Controls.Clear();

switch (ViewMode)
{
case "Edit":
AuthoringPlaceholder();
break;
case "default":
TextPlaceHolder();
break;
}
base.CreateChildControls();
}
protected void AuthoringPlaceholder()
{
tb = new TextBox();
this.tb.ID = this.ID;
this.tb.TextMode = TextBoxMode.MultiLine;
//this.tb.Text = Text; Don't need to set this
this.tb.Columns = 40;
this.tb.Rows = 15;

Controls.Add(this.tb);
}
protected void TextPlaceHolder()
{
this.Controls.Add(new LiteralControl(this.Text));
}
}

In your page class you can switch modes like this:

protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack)
{
test.ViewMode = "default";
}
}

And place it in the page like this:

<cc1:HTMLPlaceholder runat=server ViewMode="Edit" id="test" />
<asp:Button runat="server" ID="submit" Text="submit" />
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top