Textbox next to the RadioButtonList - asp.net

I need to create a radiobuttonlist containing a "other" option, and i have to put a textbox next to it. Here is what i did.
if(!ispostpage){
PlaceofWork.DataSource = workplace;
PlaceofWork.DataBind();
PlaceofWork.DataTextField = "WorkPlace1";
PlaceofWork.DataValueField = "WorkID";
PlaceofWork.Items.Add(new ListItem("Other - Specify<input name=\"OtherWorkPlace\" type=\"text\" value=\"test\" id=\"OtherWorkPlace\"/>", "-1"));
This radiobuttonlist is in a usercontrol.
at the first I didn't add if(!ispostpage) so when i try Request.Form["OtherWorkPlace"], it didn't return anything
after i add the code if(!ispostpage), it pop up the error "Object reference not set to an instance of an object"
So how can I get the value of the input textbox?

Not sure if this would help you out, but wouldn't it help if you place a asp:TextBox control in the page and retrieve the value from it only if 'Other' radio button is checked? This text box can be made visible in the client side once the 'Other' radio button is checked. The text box can be placed next to the radio button using CSS.

You could use a hidden field control on the asp .net side.
<asp:HiddenField runat="server" ID="rbOtherText" />
The set the value of the control using a javascript onblur event.
PlaceofWork.Items.Add(new ListItem("Other - Specify<input name=\"OtherWorkPlace\" type=\"text\" value=\"test\" onblur=\"document.getElementById('" & rbOtherText.ClientID & "').value = this.value;\" />", "-1"));
Then in the code behind just reference the HiddenField.

The runat="server" is not buying you anything, it's probably just being rendered directly into the output. If you can see it when you View Source on the page, then it's not being processed as a server side control. I would get rid of that.
Add an ID attribute with the same value as the name attribute:
PlaceofWork.Items.Add(new ListItem("Other - Specify<input id=\"OtherWorkPlace\" name=\"OtherWorkPlace\" type=\"text\" value=\"test\"/>", "-1"));
Remember that IDs must be unique, so you can only have one of these per page without changing the naming convention. Then you are able to see it in the Form collection, as you previously tried.
ASPX
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%# Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:WebUserControl1 ID="WebUserControl11" runat="server" />
<br />
<asp:Button ID="Button1" runat="server" Text="Submit" />
</div>
</form>
</body>
</html>
ASPX Code behind
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
string result = Request.Form["OtherWorkPlace"].ToString();
}
}
ASCX
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
</asp:RadioButtonList>
ASCX Code behind
protected void Page_Load(object sender, EventArgs e)
{
var list = new List<string>();
list.Add("1");
list.Add("2");
list.Add("3");
if (!IsPostBack)
{
RadioButtonList1.DataSource = list;
RadioButtonList1.DataBind();
//RadioButtonList1.DataTextField = "Value";
//RadioButtonList1.DataValueField = "Key";
RadioButtonList1.Items.Add(new ListItem("Other - Specify<input id=\"OtherWorkPlace\" name=\"OtherWorkPlace\" type=\"text\" value=\"test\" />", "-1"));
}
}
If your RadioButtonList is in a UserControl, it sounds like you want to re-use this in multiple places, possibly even on the same page. If so, you are definitely going to have to come up with a way to manage the IDs so they don't conflict.

Related

Keep a value accessible in Page.Init between postbacks in asp.net

Ok, I've already learned that in order to keep the dynamic (created) controls and their viewstate in asp.net we must (re)create them in the Page init event, so they already exist within the page's control hierarchy before the view state is loaded.
As it says in this article.
There is no problem to achieve this behaviour if the criteria to create these controls is outside the web environment, for example a database. But what should I do if what I use to decide how many dynamic controls I have to create is actually a value that is in the controls?
I try to explain it with an example, maybe it's clearer:
Let's say that we have a textbox and two buttons. In the textbox I write the number of how many dynamic controls I want to create, for example 4 checkbox. When I hit the button1 the controls should be created. No problem. Then I check some checkboxes and hit the button2 just to fire a postback. Now I should recreate the controls in the page init event, like we said before, in order to maintain the controls and their state.
And here comes the problem. Because of I'm in the init stage I have no viewstate so I'm no able to access the value in the textbox that tells me how many dynamic checkbox should I create.
I thought that storing the value in the session object would do the trick, but it doesn't. The session object is no accessible as well.
Where can I save the value that it'll be accessible from the init event too?
Thanks and sorry for the long post!
First thing - textbox value is not stored/retrieved from view state, you cannot get textbox value from viewstate.
Coming to actual problem, here is the sequence of (imp) events init -> load view state -> bind postback data -> page load. You can retrieve textbox value only after bind postback data event (which actually takes posted data and binds to the textbox control).
In init only option is to use Request.Form{"textboxid"] to get the textbox value.
You are on the right track.
If you use TextBox, you do not need another ViewState to keep track of how many controls has been created, because TextBox control has its own ViewState already.
You can use either Page_Init or Page_Load to load control back.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="WebApplication2010.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox runat="server" ID="NumberTextBox" />
<asp:Button runat="server" ID="CreateControlButton"
OnClick="CreateControlButton_Click"
Text="Create Control" />
<br />
<asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
</div>
</form>
</body>
</html>
using System;
using System.Web.UI;
namespace WebApplication2010
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
int ids;
if (Int32.TryParse(NumberTextBox.Text, out ids))
{
for (int i = 0; i < ids; i++)
{
Control ctrl = Page.LoadControl("WebUserControl.ascx");
ctrl.ID = i.ToString();
PlaceHolder1.Controls.Add(ctrl);
}
}
}
}
protected void CreateControlButton_Click(object sender, EventArgs e)
{
}
}
}
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="WebUserControl.ascx.cs"
Inherits="WebApplication2010.WebUserControl" %>
<asp:CheckBox runat="server" ID="CheckBox1" />
<asp:Button runat="server" ID="Button1" OnClick="Button_Click"
Text="Post Back" />
<asp:Label runat="server" ID="Label1" />
<br />
using System;
namespace WebApplication2010
{
public partial class WebUserControl : System.Web.UI.UserControl
{
protected void Button_Click(object sender, EventArgs e)
{
Label1.Text = " This control was posted back.";
}
}
}
This is the common paradox with page lifecycle when you work with code behind. For example, you save the editing customerid in viewstate but controls need to bind on init to be able to read their posted values.
Best real life solution is to do what bound controls do on postback, call explicilately the LoadPostBackData on IPostBackDataHandler interface that all controls implement, after you have created them in Page Load event.
You should create an extension method for Controls and call it when needed:
control.DataBind();
control.LoadPostedData(); // extension method

ASP Data-binded dropdown list without autopostback

I have a simple form with a dropdown list binded to a string array (as a simple example). The form is submitted when the user clicks a button.
I want to query the selected item in the list. I read the SelectedValue member of the dropdownlist which always contains the default item no matter what I select in the form.
I can't use autopostback on the list as in my production environment the form is displayed in dynamic div using jquery.
If I remove the binding and add the list items in the asp file using ListItems tags, than it magically works.
My sample asp code:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:DropDownList ID="DropDownList1" runat="server">
</asp:DropDownList>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</div>
</form>
</body>
</html>
And the code-behind file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string[] items = { "bindItem1", "bindItem2", "bindItem3" };
DropDownList1.DataSource = items;
DropDownList1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
string text = TextBox1.Text;
string item = DropDownList1.SelectedValue;
}
}
In the page_load do the databinding only if Page.IsPostBack==False.
if (!IsPostBack)
{
//do the data binding
}
Your code now on every page load, will bind the data again and again, so the selected value is "not" changing.

How to dynamically render a control?

How do I go about rendering an asp.net control on a web page from a string in code behind?
For example, say I have the aspx page below:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="nrm.FRGPproposal.Questionnaire1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
//want to render a text box here
</div>
</form>
</body>
</html>
What could I do in my Page_Load event to render a TextBox into the div?
protected void Page_Load(object sender, EventArgs e)
{
//what do i do here to render a TextBox in the div from the aspx page?
}
Caution there may be compilation problems here. But basically add a placeholder control to the code in front as such.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="nrm.FRGPproposal.Questionnaire1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:placeholder id="placeHolder" runat="server"/>
</div>
</form>
</body>
</html>
Then create a TextBox in the code behind programmatically. You will need to include System.Web.UI in order to get the textbox.
Then Add the control to the controls collection on the placeHolder. Set whatever properties you like on the text box programmatically
protected void Page_Load(object sender, EventArgs e)
{
TextBox tb = new TextBox();
placeHolder.Controls.Add(tb); //tb is referring to the name that you want to name your element. in this example given was TextBox. so the name of text box is tb.
}
Easy.
Add two attributes to your div element : <div runat="server" id="myDiv"></div>
Then
TextBox tb = new TextBox();
this.myDiv.Controls.Add(tb);
If you want to render a Custom UserControl you can use the above code
MyUserControl control = (MyUserControl)Page.LoadControl("~/My_VirtualPathToControl");
this.myDiv.Controls.Add(control);
(You must register your control in the aspx file)
One more think.
Be cautious when you execute code on Page_Load event.
You will also need to rebuild the controls in the Page_Init method in order to read the controls' state/values on PostBack.
protected void Page_Init(object sender, System.EventArgs e)
{
TextBox tb = new TextBox();
placeHolder.Controls.Add();
}

ASP.NET TextBox OnTextChanged triggered twice in Firefox

Hi I'm facing a weird problem that only happens in FF. I have a TextBox control with OnTextChanged handler. The event handler is working fine most of the time, but when the user changed the text and press Enter in FF, the OnTextChanged event is called twice. I observed the problem in Firebug that the first request is actually canceled because of the second event.
Test.aspx
<%# Page Language="C#" AutoEventWireup="True" CodeFile="~/Test.aspx.cs" Inherits="T.Test" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Custom TextBox - OnTextChanged - C# Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<asp:ScriptManager runat="server" ID="SM">
</asp:ScriptManager>
<h3>Custom TextBox - OnTextChanged - C# Example</h3>
<asp:UpdatePanel runat="server" ID="Panel1">
<ContentTemplate>
<asp:Panel runat="server" ID="Panel2">
<asp:TextBox ID="TextBox1" AutoPostBack="true" OnTextChanged="OnTextChanged" runat="server">Hello World!
</asp:TextBox>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Test.aspx.cs
using System;
using System.Web.UI;
namespace T
{
public partial class Test : Page
{
protected void OnTextChanged(object sender, EventArgs e)
{
var a = 0;
}
}
}
Put a break point # var a, and you'll be able to see that after changing text and press enter in FF (v3.5.7), the OnTextChanged event is invoked twice.
So my question is, what's the best way to properly handle OnTextChanged event so that hitting enter in the textbox doesn't trigger double postback.
Regards,
I don't know why it's isolated to FireFox, but if you remove the AutoPostBack property, that will solve the problem.
There is also an explanation here of why it's posting back twice.
I know its an old thread but maybe helpful for others.
I had the same issue when validating the text entered. I was getting 2 events fired so I put this script at the top of the page which causes the enter to just tab to the next control instead of submitting the form. The text box remained the same AutoPostBack="true" OnTextChanged="xxx_TextChanged"
''''
<script type="text/javascript">
$('body').on('keydown', 'input, select', function (e) {
if (e.key === "Enter") {
var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
focusable = form.find('input,a,select,button,textarea').filter(':visible');
next = focusable.eq(focusable.index(this) + 1);
if (next.length) {
next.focus();
} else {
form.submit();
}
return false;
}
});
</script>
''''

Can multiple filters be used on a llblgen data source?

I have the following (sample)code to filter search results from a LLBLGen data source:
IPredicateExpression firstFilter = new PredicateExpression();
firstFilter.Add(new FieldLikePredicate(CustomerFields.FirstName, null, txtSearchFirst.Text.Trim() + "%"));
llbldsCustomer.FilterToUser = firstFilter;
llbldsCustomer.DataBind();
gridview1.DataBind();
This works fine and filters the results when I trigger this code. However, if I add a second filter, I have to press invoke the code twice before I see results. Below is the snippet with 2 filters:
IPredicateExpression firstFilter = new PredicateExpression();
firstFilter.Add(new FieldLikePredicate(CustomerFields.FirstName, null, txtSearchFirst.Text.Trim() + "%"));
firstFilter.Add(new FieldLikePredicate(CustomerFields.LastName, null, txtSearchLast.Text.Trim() + "%"));
llbldsCustomer.FilterToUser = firstFilter;
llbldsCustomer.DataBind();
gridview1.DataBind();
The issue is fine for every search after the first one; however, I need it to work on the first one.
UPDATE:
The code is located in an ASP.Net Button Click event. There is no code in the Page Load event block that affects this data source either.
Any ideas?
I am unable to duplicate the behavior you are seeing in a simple test case (see below). Also, unless you are using parameter binding on the datasource, you shouldn't have to call DataBind on the DataSource control but only on the GridView.
Test Case:
DB contains 1 table Customer with two varchar(50) fields: FirstName and LastName.
Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestWebApp1._Default" %>
<%# Register Assembly="SD.LLBLGen.Pro.ORMSupportClasses.NET20" Namespace="SD.LLBLGen.Pro.ORMSupportClasses" TagPrefix="llblgenpro" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
<br />
<br />
<asp:GridView ID="CustomersGridView" runat="server" DataSourceID="dsCustomers">
</asp:GridView>
</div>
<llblgenpro:LLBLGenProDataSource ID="dsCustomers" runat="server"
DataContainerType="EntityCollection"
EntityCollectionTypeName="TestWebApp1Framework.CollectionClasses.CustomerCollection, TestWebApp1Framework">
</llblgenpro:LLBLGenProDataSource>
</form>
</body>
</html>
Default.aspx.cs:
using System;
using SD.LLBLGen.Pro.ORMSupportClasses;
using TestWebApp1Framework.HelperClasses;
namespace TestWebApp1
{
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
var filter = new PredicateExpression();
filter.Add(new FieldLikePredicate(CustomerFields.FirstName, null, TextBox1.Text.Trim() + "%"));
filter.AddWithOr(new FieldLikePredicate(CustomerFields.LastName, null, TextBox1.Text.Trim() + "%"));
dsCustomers.FilterToUse = filter;
dsCustomers.DataBind();
CustomersGridView.DataBind();
}
}
}
Test Results:
Loading this page initially shows all customers. Entering the letter A into the textbox and clicking the button shows a list of all customers whose first name or last name starts with A. This shows that both filters are working correctly.

Resources