I have a user control with a text box and a button. When I press the button, I try to read the contents using the text box's ID (from the user control's code behind) but I always get a blank result. What is the proper way to reference a control in a user control from the same user control.
I read elsewhere that I should simply use the control ID, but somehow it is not working. I must be doing something wrong and I am hoping this is a common mistake and that someone can she some light on this.
Edit:
Markup:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="ForumPostControl.ascx.cs" Inherits="ForumPostControl" debug="true" %>
<div id="PostDiv" runat="server">
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="border:1px solid white; border-radius:5px; margin-bottom:5px;">
<tr>
<td valign="top" width="52" style="text-align:center; padding:10px 0px 10px 0px; border-bottom:1px dashed #FFF;">
<asp:Image ID="imgReplyPoster" runat="server" />
</td>
<td valign="middle" style="text-align:left; padding:10px 0px 10px 0px; border-bottom:1px dashed #FFF;">
<asp:HyperLink ID="lnkReplyPoster" runat="server">lnkReplyPoster</asp:HyperLink><br />
<asp:Label ID="lblCreated" runat="server" Text="Label"></asp:Label>
</td>
<td style="text-align:right; padding:10px 20px 10px 0px; border-bottom:1px dashed #FFF;">
<asp:LinkButton ID="btnReply" runat="server" onclick="btnReply_Click">Reply</asp:LinkButton>
<asp:LinkButton ID="btnDelete" runat="server" OnClick="btnDelete_Click" OnClientClick="return ConfirmClick('Do you really want to delete this post?');"><img src="images/icons/trash16.png" alt="Delete" border="0" /></asp:LinkButton>
</td>
</tr>
<tr>
<td valign="top" align="justify" style="padding:10px;" colspan="3">
<asp:Literal ID="ltrlPostBody" runat="server"></asp:Literal>
</td>
</tr>
</table>
<asp:PlaceHolder ID="phReply" runat="server" Visible="False">
<div align="center" style="padding:5px 10px 10px 10px;">
<asp:HiddenField ID="hdnParentID" runat="server" />
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<asp:TextBox ID="txtReply" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td align="right" style="padding-top:20px;">
<asp:LinkButton ID="lnkPostReply" runat="server" OnClick="lnkPostReply_Click">Post reply</asp:LinkButton>
</td>
</tr>
</table>
</div>
</asp:PlaceHolder>
</div>
Code behind for saving text to database:
protected void lnkPostReply_Click(Object sender, EventArgs e)
{
String connectionString = (String)System.Configuration.ConfigurationManager.AppSettings["ConnectionString"];
SqlConnection cnn = new SqlConnection(connectionString);
SqlCommand cmd;
String strSQL;
cnn.Open();
strSQL = "INSERT INTO ForumThreads (ForumID, ParentID, PostBody, Created, CreatedBy, Modified, ModifiedBy) VALUES " +
"(#ForumID, #ParentID, #PostBody, GETDATE(), #CreatedBy, GETDATE(), #CreatedBy);";
cmd = new SqlCommand(strSQL, cnn);
cmd.Parameters.AddWithValue("#ForumID", prvForumID);
cmd.Parameters.AddWithValue("#ParentID", prvForumThreadID);
cmd.Parameters.AddWithValue("#PostBody", txtReply.Text);
cmd.Parameters.AddWithValue("#CreatedBy", CurrentMember.MemberID);
cmd.ExecuteNonQuery();
cmd.Dispose();
cnn.Close();
cnn.Dispose();
Response.Redirect("forum_topic.aspx?TID=" + prvEncryptedTID);
}
The problem is with reading the txtReply control.
Edit #2
I am still struggling with this and experimenting stuff. Here are some finding, I hope they can help solve the mystery. I noticed that I can read properties from the text box control such as width and ID but I cannot read the text that is entered by the user. It always returns blank. If I pre set the text programmatically to, say, "Initial Text", then when I try to read the .text property, I still get "Initial Text", no matter what the user enters. It is as if the text typed the user is lost on post back.
As you mentioned that you are using the usercontrol inside a repeater, I would check the page's Page_Load event method to see I am not rebinding the repeater at postback:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Repeater1.DataSource = GetData();
Repeater1.DataBind();
}
}
And my Repeater1_ItemDataBound may look something like:
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
ForumPostControl myControl = (ForumPostControl)e.Item.FindControl("ForumPostControl1");
myControl.MyProperty = 20;//My custom property of user control
}
}
Now, each postback may wipe out my usercontrol's custom property. I need to make sure it persist on postback. In my ForumPostControl.ascx.cs I would store the value of this property in visestate and retrieve when needed. I should have this code in my usercontrol:
public int MyProperty
{
get
{
int myProperty = 0;
if (ViewState["MyProperty"] != null)
{
int.TryParse(ViewState["MyProperty"].ToString(), out myProperty);
}
return myProperty;
}
set
{
ViewState["MyProperty"] = value;
}
}
Related
I used a asp:button to bind the data from a textbox into a grid, but my problem was getting the page to stop refreshing. So I changed the asp:button to html button, because it was server side causing the page to refresh. Now I dont know how to use the same c# code to bind the data using html button.
Here's an example of my c# code:
//Site Class
class Sites
{
//Strings and variables are created based off text box Id to make matter easier to read
public string SiteName { get; set; }
public string Slick { get; set; }
public string UserID { get; set; }
}
//Created a new list based on class.
//Items are added based on whats in the textboxes
//and events are fired to gridview by the click of the class button
protected void SiteDetails_Click(object sender, EventArgs e)
{
List<Sites> list;
if (Session["list"] == null)
{
list = new List<Sites>();
}
else
{
list = (List<Sites>)Session["list"];
}
list.Add(new Sites() { SiteName = Sname.Text, Slick = Slick.Text, UserID = User_ID.Text });
Session["list"] = list;
SiteGrid.DataSource = list;
SiteGrid.DataBind();
}
And This is my Html aspx page:
Site Details
SiteName:
<td style="width: 102px; height: 8px;">Slic:</td>
<td style="width: 153px; height: 8px;">
<asp:TextBox ID="Slick" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td style="width: 129px; margin-left: 40px; height: 23px;">User ID:</td>
<td style="width: 152px; height: 23px;">
<asp:TextBox ID="User_ID" runat="server" style="font-weight: bold"></asp:TextBox>
</td>
<td style="width: 102px; height: 23px;">
Password:</td>
<td style="width: 153px; height: 23px;">
<asp:TextBox ID="Pass" runat="server" TextMode="Password" ></asp:TextBox>
</td>
</tr>
<%-- //Site Button--%>
<tr>
<td></td>
<td>
<button ID="SiteDetails" OnClick="SiteDetails_Click()">AddSites</button>
</td>
</tr>
</table>
<%-- //Site GridView--%>
<asp:GridView ID="SiteGrid" class="table-bordered table-hover tableGridLines="None">
</asp:GridView>
I've made a basic Login Page using textboxes. I'm validating the users from the database created. Below is my backend code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
SqlDataReader sdrDatanew = null; //Read rows one by one.
string strnew;
string connectionString = WebConfigurationManager.ConnectionStrings["Gen_LicConnectionString"].ConnectionString; //Define new connectionstring
SqlConnection connew = new SqlConnection(connectionString); //establishes a new sql connection
connew.Open(); //Opens Connection
strnew = "select User_Type from User_Details where User_Type='" + ddlUserSel.SelectedItem.Value + "' AND LoginID = '" + txtUserName.Text + "' AND Password = '" + txtPassword.Text + "'";
SqlCommand sqlCommnew = new SqlCommand(strnew, connew); //passes the command and connection
sdrDatanew = sqlCommnew.ExecuteReader(); //For select command
int userType = 0;
if (sdrDatanew.HasRows)
{
if (sdrDatanew.Read())
{
userType = Convert.ToInt32(sdrDatanew["User_Type"].ToString());
}
}
switch (userType)
{
case 0:
Response.Redirect("Lic_Gen.aspx");
break;
case 1:
Response.Redirect("Cust_Page.aspx");
break;
default:
lblDisp.Text= "Invalid User/Password";
break;
}
connew.Close();
}
This is my frontend code:
<div>
<h2 class="style12">
LOGIN</h2>
<p class="style10">
</p>
<table align="center" cellpadding="2" cellspacing="5" style="border-width: thick;
border-style: outset; height: 195px;" class="style14">
<tr>
<td class="style16" style="border-style: none; font-family: 'Times New Roman', Times, serif;
font-size: 17.5px; font-weight: bold; font-style: normal">
User Type</td>
<td class="style17">
<asp:DropDownList ID="ddlUserSel" runat="server" Height="25px" Width="260px" CssClass="drp">
<asp:ListItem Value="0">Admin</asp:ListItem>
<asp:ListItem Value="1">Customer</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td class="style16" style="border-style: none; font-family: 'Times New Roman', Times, serif;
font-size: 17.5px; font-weight: bold; font-style: normal">
Login
</td>
<td class="style17">
<asp:TextBox ID="txtUserName" runat="server" Width="250px" CssClass="Textbox1" MaxLength="15"></asp:TextBox>
<asp:RequiredFieldValidator ID="reqUserName" runat="server" ErrorMessage="*" ForeColor="Red"
ControlToValidate="txtUserName" Font-Size="Large"></asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td class="style16" style="font-family: 'Times New Roman', Times, serif; font-size: 17.5px;
font-weight: bold; font-style: normal">
Password
</td>
<td class="style17">
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" Width="250px" CssClass="Textbox1" MaxLength="15"></asp:TextBox>
<asp:RequiredFieldValidator ID="reqPassword" runat="server" ErrorMessage="*" ForeColor="Red"
ControlToValidate="txtPassword" Font-Size="Large"></asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Label ID="lblDisp" runat="server" ForeColor="Red"></asp:Label>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnSubmit" runat="server" CssClass="btn1" Text="Submit"
OnClick="btnSubmit_Click" Width="80px"/>
<asp:Button ID="btnCancel" runat="server" CssClass="btn1" Text="Cancel"
OnClick="btnCancel_Click" Width="80px"/>
</td>
</tr>
</table>
</div>
Now I'm having the following issues:
Irrespective of the user type, the page always gets redirected to Lic_Gen.aspx.
Even if I enter the wrong password, the page still gets redirected to Lic_Gen.aspx.
The page should also check whether the userType entered i.e. Admin or Customer should be valid with that particular Login ID and Password. But I can't get to that either.
I know these issues are arriving because of the fact I've explicitly defined UserType value as 0.
When I tried converting it with the following code:
int userType = Convert.ToInt32(strnew); it doesn't work.
So any guidelines on how to improve my basic page?
The code you have written is wrong. It will redirect even if wrong password is entered since you give a value 0 to userType even if no results is returned from the sql query. Also I am assuming that the query is not returning any values which is creating the page to get redirected everytime to Lic_Gen.aspx . I recommend you to have a look at ASP membership framework which provides all this functions without all these codes...
Based on provided code, possible problems are :
No data returned in sdrDatanew, hence the userType always remains 0
Data from DB returned under sdrDatanew["User_Type"] is always 0 (string), hence the userType always remains 0
Please use above points to debug further and I see no issues in code.
CAUTION : Your code is vulnerable to SQL Injection attack. Please read details # http://en.wikipedia.org/wiki/SQL_injection. If you are planning to publish this web site somewhere, you will be in trouble for sure.
Do not use sdrDatanew.HasRows, only check Data reader Read() method:
int userType = -1;
if (sdrDatanew.Read())
{
userType = Convert.ToInt32(sdrDatanew["User_Type"].ToString());
}
Gooday. I have a login control, with an integrated user textbox and login button. I did this little test to see how it works, and surprisingly, after doing this:
protected void LoginButton_Click(object sender, EventArgs e)
{
TextBox userTextBox = (TextBox)Login1.FindControl("UserName");
userTextBox.Text = "You pressed the button";
}
the userTextBox doesn't change to "You pressed the button". Why?
Thanks. Anna
EDIT: Sure, here is the markup (most of it is generated automatically by the system when adding the Login control); you will notice a button LoginButton integrated in the Login:
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:Panel ID="searchPanel" runat="server" DefaultButton="login1$LoginButton">
<asp:Login ID="Login1" runat="server"
FailureText="Logarea a esuat. Reincercati!" LoginButtonText="Logati-va!"
PasswordLabelText="Parola:"
PasswordRequiredErrorMessage="Trebuie sa introduceti parola."
RememberMeText="Tine-ma minte!" TitleText="Logare"
UserNameLabelText="Nume de utilizator:"
UserNameRequiredErrorMessage="Trebuie sa introduceti numele de utilizator.">
<LayoutTemplate>
<table border="0" cellpadding="1" cellspacing="0"
style="border-collapse:collapse;">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Logare</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">Nume
de utilizator:</asp:Label>
</td>
.........
<tr>
<td align="right" colspan="2">
<asp:Button ID="LoginButton" runat="server" CommandName="Login"
Text="Logati-va!" ValidationGroup="Login1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</LayoutTemplate>
</asp:Login>
</asp:Panel>
</asp:Content>
The code-behind goes liek this:
namespace Cinemax
{
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//userTextBox.Focus(); // this sets the focus on the username textbox when the page loads
this.Title = CinemaxConfiguration.SiteName + ": Login";
}
protected void LoginButton_Click(object sender, EventArgs e)
{
TextBox userTextBox = (TextBox)Login1.FindControl("UserName");
TextBox userPassword = (TextBox)Login1.FindControl("Password");
//Button loginBtn = (Button)Login1.FindControl("LoginButton");
userTextBox.Text = "You pressed me";
if (User1.ConnAttempt(userTextBox.Text, userPassword.Text) == 1)
{
Session["User"] = userTextBox.Text;
Response.Redirect("Catalog.aspx");
}
else
{
}
}
}
}
Is the TestBox an ASP server control, and is runat=Server?
I might be wrong, but do you ever actually bind it back to the control.
You are creating a new textbox that is initialised from your login control.
You then set the text of that textbox, but i dont think thta will bind it back to the control itself.
If you debug the application, does it show that the text gets set?
also, do you have something in the Page_Load method that sets the text box value? you should put things in a
if(!IsPostBack)
{
userTextBox.Text = ""
}
statement
check if your control is runat=server and you have binded the control to the event
this.LoginButton.Click += new System.EventHandler(this.LoginButton_Click);
In your login control check if you are setting some value of userTextBox in Page_Load or any other event, as it appears that its value is being set from somewhere else.
you have to bind it to the Form. . .
in a repeater, i want to do a function on every item bounded, example
<asp:Repeater runat="server" ID="rptArticleContent"
OnItemDataBound="rptArticleContent_ItemDataBound">
<ItemTemplate>
<tr>
<td width="365" valign="top" align="left" class="bodyContent" bgcolor="#FFFFFF">
<div>
<h2 class="h2">
<asp:Label runat="server" ID="dsds"> <%#Eval("Title") %></asp:Label>
</h2>
<div class="article-body">
<div class="Article-image">
<%#Eval("Image") %>
</div>
<%#Eval("Description") %>
</div>
<asp:Literal runat="server" ID="litArticleSource" Text='<%#Eval("Source") %>'>
</asp:Literal>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
in code behind i want to do some manipulation on the data inside the Literal
protected void rptArticleContent_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Literal litArticleSource = rptArticleContent.FindControl
("litArticleSource") as Literal;
string ArticleSourcesR = litArticleSource.Text;
}
ArticleSourcesR still gives null, somes told me that when catching the controle with rptArticleContent.FindControl i should add something so it would be applied on every item bounded, what is that missing clue.?? what should be added?
You don't want to use rptArticleContent in the function, rather e.Item which will return the current repeater item instance.
Given the following HTML:
<asp:content id="Content1" contentplaceholderid="mainContent" runat="server">
<div class="scrollRow">
<table width="100%">
<tr>
<td width="25%">Site name: <b>My site</b></td>
<td>Created on 12th Aug 2010</td>
<td align="right"><button onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>
</div>
<div class="scrollRow">
<table width="100%">
<tr>
<td width="25%">Site name: <b>Another site</b></td>
<td>Created on 3rd Aug 2010</td>
<td align="right"><button onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>
</div>
<div class="scrollRow scrollRowOn">
<table width="100%">
<tr>
<td width="25%">Site name: <b>Another site</b></td>
<td>Created on 3rd Aug 2010</td>
<td align="right"></td>
</tr>
</table>
</div>
</asp:content>
Which is a list of rows, how am I programatically meant to generate these after I have retrieved the SQL rows from the code behind? Do I need to make my own control, or something along those lines?
Try something along these lines:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_OnItemDataBound">
<ItemTemplate>
<div class='<%# SetClass(Eval("SiteId")) %>'>
<table width="100%">
<tr>
<td width="25%">Site name: <b><%# Eval("SiteName") %></b></td>
<td>Created on <%# DataBinder.Eval(Container.DataItem, "CreateDate", "{0:dd MMM yyyy}")%></td>
<td align="right"><button id="btnRevert" runat="server" onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
In the codebehind Repeater1_OnItemDataBound event you could set the button to be visible or not, depending on whether the item is the current one.
protected void Repeater1_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if (item.ItemType == ListItemType.AlternatingItem || item.ItemType == ListItemType.Item)
{
Site site = e.Item.DataItem as Site; //List<Site> is what you are binding to the repeater
if (site.SiteId == currentSiteId)
{
var btn = e.Item.FindControl("btnRevert") as Button;
if (btn != null)
{
btn.Visible = false;
}
}
}
}
CSS Classes for your items can be set like this:
protected string SetClass(object obj) {
int siteId;
if (int.TryParse(obj.ToString(), out siteId)){
if (siteId == currentSiteId) //currentSiteId determined elsewhere
{
return "scrollRow";
}
}
return "scrollRow scrollRowOn";
}
There are a lot of ways to get to this, of course, but here's one (possibly not the best, but that's subjective anyway):
Assuming C# web forms and ADO.Net, and assuming you need precisely that html, you could loop over the rows in the DataSet and output the html.
DataSet ds = {data set from your sql}
StringBuilder html = new StringBuilder();
foreach (DataRow row in DataSet.Tables[0].Rows) {
html.Append( string.Format(#"<div class=""scrollRow"">
<table width=""100%"">
<tr>
<td width=""25%"">Site name: <b>{0}</b></td>
<td>Created on {1}</td>
<td align="right"><button onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>",row["sitename"], row["createdate"]));
}
You could include the html by having an <asp:Literal> in the page code and setting the Text property.
You could also do it by creating System.Web.UI.WebControls.Table nodes in the code behind and adding TableRows and TableCells to them, using the same loop, and then adding those to the page using. Given what you've given us thus far, you seem to be adding controls to a page with a MasterPage, so you would need to add your tables to the Master's ContentPlaceHolder, which you can find and add controls to like so:
ContentPlaceHolder ph = (ContentPlaceHolder)this.Master.FindControl( "ContentPlaceHolder1" );
foreach (DataRow row in DataSet.Tables[0].Rows) {
Panel pnl = new Panel();
Table tbl = new Table();
TableRow tblrow = new TableRow();
TableCell cell1 = new TableCell();
cell1.Text = string.Format("Site name: <b>{0}</b>",row["sitename"]);
row.Cells.Add(cell1);
tbl.Rows.Add(tblrow);
pnl.Controls.Add(tbl);
ph.Controls.Add(pnl);
}
You can set properties on the TableRows and TableCells, but if you do it this way you will lose some control over the html that's generated, most notably the html ID attributes. You don't seem to be using those, so perhaps that's ok.
I would suggest the repeater control. You can use it something like this:
<asp:Repeater runat="server" id="myRepeater">
<ItemTemplate>
<div class="scrollRow scrollRowOn">
<table width="100%">
<tr>
<td width="25%">Site name: <b><% Eval("SiteName")%></b></td>
<td>Created on <% Eval("CreatedOn")%></td>
<td align="right"></td>
</tr>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
Then you need to bind your data to it in the Page_Load event:
myRepeater.DataSource = myData;
myRepeater.DataBind();
Where my data is the data that you retrieve from the database.