|
-
Apr 22nd, 2005, 11:59 AM
#1
Thread Starter
Not NoteMe
Custom control Properties
I've got a custom control as listed below (in C#)
Code:
public class LoginControl : System.Web.UI.WebControls.WebControl
{
private System.Web.UI.WebControls.TextBox txtusername = new TextBox();
private System.Web.UI.WebControls.TextBox txtpassword = new TextBox();
private System.Web.UI.WebControls.Button cmdLogon = new Button();
private System.Web.UI.WebControls.RequiredFieldValidator reqUsername = new RequiredFieldValidator();
private System.Web.UI.WebControls.RegularExpressionValidator revPassword = new RegularExpressionValidator();
[Bindable(true),Category("TextBoxContents")]
public string Username
{
get
{
return txtusername.Text;
}
set
{
txtusername.Text = value;
}
}
public string Password{
get
{
return txtpassword.Text;
}
set
{
txtpassword.Text = value;
}
}
public LoginControl()
{
txtusername.Width = 140;
txtpassword.Width = 140;
txtusername.MaxLength = 15;
txtpassword.MaxLength = 15;
txtusername.TextMode = TextBoxMode.SingleLine;
txtpassword.TextMode = TextBoxMode.Password;
cmdLogon.Text = "Logon";
cmdLogon.Attributes.Add("OnServerClick","Submit_Click");
//reqUsername.Text = "Username must not be blank";
reqUsername.Display = ValidatorDisplay.Dynamic;
reqUsername.EnableClientScript = true;
reqUsername.ErrorMessage = "Username must not be blank";
reqUsername.ControlToValidate = "txtusername";
reqUsername.Visible = false;
revPassword.Display = ValidatorDisplay.Dynamic;
revPassword.EnableClientScript = true;
revPassword.ErrorMessage = "Password must be at least 6 alpha-numeric charactors";
revPassword.ControlToValidate = "txtpassword";
revPassword.Visible = false;
}
/// <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)
{
output.Write("<table border=\"1\" width=\"300\" id=\"table1\">");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Username:</td>");
output.Write("<td border=\"0\">");
txtusername.RenderControl(output);
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Password:</td>");
output.Write("<td border=\"0\">");
txtpassword.RenderControl(output);
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\"><td colspan=\"2\"><div align=\"centre\">");
cmdLogon.RenderControl(output);
output.Write("<br>");
reqUsername.RenderControl(output);
output.Write("<br>");
revPassword.RenderControl(output);
output.Write("</div></td></tr>");
output.Write("</table>");
}
}
When i put it on my page i can change the username and password properties at design time.
Page code is below:
Code:
<%@ Page Language="C#" %>
<%@ Register TagPrefix="n0" Namespace="George" Assembly="LoginControl" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Data.SqlClient" %>
<%@ import Namespace="System.Web.Security" %>
<script runat="server">
private void Page_Load(Object sender, EventArgs E)
{
Page.Validate();
if ((Page.IsPostBack) && (Page.IsValid))
{
SqlConnection myConnection = new SqlConnection("server=GEORGE;database=MyDB;Trusted_Connection=yes");
SqlCommand myCommand = new SqlCommand("SELECT People.Nickname, People.Password FROM People WHERE People.Nickname='" + ctrlLogin.Username + "'", myConnection);
try
{
myConnection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
if(dr.Read())
{
if(dr.GetString(1).Trim() == ctrlLogin.Password.Trim())
FormsAuthentication.RedirectFromLoginPage(ctrlLogin.Username, false);
else
Message.Text = "Sorry! Your password is incorrect.</br>Please log in again.";
}
else
Message.Text = "Your username is wrong!</br>Please log in again.";
}
catch(Exception myException)
{
Response.Write("Oops! The error: " + myException.Message + " occured.");
}
finally
{
myConnection.Close();
}
Message.Text = "SELECT People.Nickname, People.Password FROM People WHERE People.Nickname='" + ctrlLogin.Username + "'";
}
}
</script>
<html>
<head>
</head>
<body style="FONT-FAMILY: arial">
<form runat="server">
<p>
<n0:LoginControl id="ctrlLogin" runat="server"></n0:LoginControl>
</p>
<p>
<asp:Label id="Message" runat="server">Label</asp:Label>
</p>
</form>
</body>
</html>
If i change them at run time it doesn't work. It's as if it's still retrieving the old value (blank) when i do ctrlLogin.Username
If i fill in the username and password at design time it works ok, however if i leave them blank, and type them in at runtime it doesn't work.
Any ideas why this is happening?
Quotes:
"I am getting better then you guys.." NoteMe, on his leet english skills.
"And I am going to meat her again later on tonight." NoteMe
"I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
"my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
Have I helped you? Please Rate my posts. 
-
Apr 22nd, 2005, 10:33 PM
#2
I wonder how many charact
Re: Custom control Properties
I don't have an IDE available to debug your code...
but from experience that I've had... may I make some suggestions:
1) Your GET/SET accessors for the UserName and Password properties should not directly set the textbox's text. They should set private variables that are also stored into Viewstate. At some point in the render (or preferably the prerender method), you can read the private variable and assign the textbox's text.
Code:
//add this to the declerations section
private const string _usernameStateKey = "usrnm";
private const string _passwordStateKey = "pswrd";
private string _username = null;
private string _password = null;
//replace username/password properties with the following
[Bindable(true),Category("TextBoxContents")]
public string Username
{
get
{
if (ViewState[_usernameStateKey] != null)
return (string)ViewState[_usernameStateKey];
else
return _username;
}
set
{
_username = value;
ViewState.Add([_usernameStateKey,value);
}
}
public string Password{
get
{
if (ViewState[_passwordStateKey] != null)
return (string)ViewState[_passwordStateKey];
else
return _password; }
set
{
_password = value;
ViewState.Add([_passwordStateKey, value);
}
}
//set the textbox's text here
private override PreRender(...)
{
EnsureChildControls();
txtusername.Text = ViewState[_usernameStateKey] == null ? _username : (string) ViewState[_usernameStateKey];
txtpassword.Text = (ViewState[_passwordStateKey] == null ?
_password : (string) ViewState[_passwordStateKey];
}
//override createchildcontrols
private override void CreateChildControls()
{
txtusername = new TextBox();
txtpassword = new TextBox();
requiredvalidatorUsername = new requiredfieldvalidator();
...
//set any properties that are not defaults here
txtpassword.TextMode = TextMode.Password;
//you then must add the controls to the container
this.Controls.Add(txtusername);
this.Controls.Add(txtpassword);
this.Controls.Add(requiredvalidatorUsername);
....
}
}
As you may have noticed, I've added an override CreateChildControls method. Simply, you should not create instances of the child controls in the declarations section, they should instead be moved to (preferably) the CreateChildControls method.
Lastly, any control property that is defaulted to a specific attribute, does not need to be explicity set. For instance, txtusername.textmode = SingleLine is unnecessary, as this is the default for the framework, and kills processing time (even though the processing time is trivial, if this app serves 1000 clients a minute, every little bit will help).
-
Apr 23rd, 2005, 10:13 AM
#3
Thread Starter
Not NoteMe
Re: Custom control Properties
Thanks for your reply.
I've changed the code as per your recommendations, listed below:
Code:
public class LoginControl : System.Web.UI.WebControls.WebControl
{
private const string _usernameStateKey = "usrnm";
private const string _passwordStateKey = "pswrd";
private string _username;
private string _password;
private System.Web.UI.WebControls.TextBox txtusername = null;
private System.Web.UI.WebControls.TextBox txtpassword = null;
private System.Web.UI.WebControls.Button cmdLogon = null;
private System.Web.UI.WebControls.RequiredFieldValidator reqUsername = null;
private System.Web.UI.WebControls.RegularExpressionValidator revPassword = null;
[Bindable(true),Category("TextBoxContents")]
public string Username
{
get
{
if (ViewState[_usernameStateKey] != null)
return (string)ViewState[_usernameStateKey];
else
return _username;
}
set
{
_username = value;
ViewState.Add(_usernameStateKey,value);
}
}
public string Password
{
get
{
if (ViewState[_passwordStateKey] != null)
return (string)ViewState[_passwordStateKey];
else
return _password;
}
set
{
_password = value;
ViewState.Add(_passwordStateKey, value);
}
}
public new void PreRender()
{
EnsureChildControls();
txtusername.Text = ViewState[_usernameStateKey] == null ? _username : (string) ViewState[_usernameStateKey];
txtpassword.Text = ViewState[_passwordStateKey] == null ? _password : (string) ViewState[_passwordStateKey];
}
protected override void CreateChildControls()
{
txtusername = new TextBox();
txtpassword = new TextBox();
cmdLogon = new Button();
reqUsername = new RequiredFieldValidator();
revPassword = new RegularExpressionValidator();
txtusername.ID = "txtusername";
txtpassword.TextMode = TextBoxMode.Password;
cmdLogon.Text = "Logon";
txtusername.Width = 140;
txtpassword.Width = 140;
txtusername.MaxLength = 15;
txtpassword.MaxLength = 15;
txtpassword.TextMode = TextBoxMode.Password;
txtpassword.ID = "txtpassword";
cmdLogon.Text = "Logon";
cmdLogon.Attributes.Add("OnServerClick","Submit_Click");
reqUsername.Display = ValidatorDisplay.Dynamic;
reqUsername.EnableClientScript = true;
reqUsername.ErrorMessage = "Username must not be blank";
reqUsername.ControlToValidate = "txtusername";
revPassword.Display = ValidatorDisplay.Dynamic;
revPassword.EnableClientScript = true;
revPassword.ErrorMessage = "Password must be at least 6 alpha-numeric charactors";
revPassword.ControlToValidate = "txtpassword";
this.Controls.Add(txtusername);
this.Controls.Add(txtpassword);
this.Controls.Add(reqUsername);
this.Controls.Add(revPassword);
}
/// <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)
{
output.Write("<table border=\"1\" width=\"300\" id=\"table1\">");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Username:</td>");
output.Write("<td border=\"0\">");
txtusername.RenderControl(output);
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Password:</td>");
output.Write("<td border=\"0\">");
txtpassword.RenderControl(output);
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\"><td colspan=\"2\"><div align=\"centre\">");
cmdLogon.RenderControl(output);
output.Write("<br>");
reqUsername.RenderControl(output);
output.Write("<br>");
revPassword.RenderControl(output);
output.Write("</div></td></tr>");
output.Write("</table>");
}
}
However, i still get the same problem, except that now if i change the property at design time, when running it i get an object reference not set error.
Any help would be greatly appreciated.
Quotes:
"I am getting better then you guys.." NoteMe, on his leet english skills.
"And I am going to meat her again later on tonight." NoteMe
"I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
"my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
Have I helped you? Please Rate my posts. 
-
Apr 26th, 2005, 03:14 PM
#4
I wonder how many charact
Re: Custom control Properties
Sorry I haven't responded (moved to a new house).
I also forgot to tell you to implement the INaming Container.
Code:
public class LoginControl : System.Web.UI.WebControls.WebControl, INaming
As far as the errors you receive when using the VS Designer:
WebControls are not 'run' when viewed in the designer per se. You need to add a second class that inherits System.Web.UI.Design.ControlDesigner.
You need to override the GetDesignTimeHtml() method.
The following MSDN reference has a good example of how to do that under the 'Creating A Custom Designer' heading.
http://msdn.microsoft.com/library/de...ebcontrols.asp
-
Apr 28th, 2005, 04:36 AM
#5
Thread Starter
Not NoteMe
Re: Custom control Properties
Thanks for your reply.
I couldn't find what you ment with the INaming container, i get a syntax error when adding it, and i did a search on MSDN but found nothing.
Regarding the extra class, i've implemented it as below, but now i get nothing appearing in the designer (looks as though the control isn't there).
Code:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Web.UI.Design;
using System.IO;
namespace George
{
/// <summary>
/// A control containing a username, password and logon button
/// </summary>
[Designer("George.LoginControlDesigner, George"), DefaultProperty("Text"),
ToolboxData("<{0}:LoginControl runat=server></{0}:LoginControl>")]
public class LoginControl : System.Web.UI.WebControls.WebControl
{
private const string _usernameStateKey = "usrnm";
private const string _passwordStateKey = "pswrd";
private string _username;
private string _password;
public System.Web.UI.WebControls.TextBox txtusername = null;
public System.Web.UI.WebControls.TextBox txtpassword = null;
public System.Web.UI.WebControls.Button cmdLogon = null;
public System.Web.UI.WebControls.RequiredFieldValidator reqUsername = null;
public System.Web.UI.WebControls.RegularExpressionValidator revPassword = null;
[Bindable(true),Category("TextBoxContents")]
public string Username
{
get
{
if (ViewState[_usernameStateKey] != null)
return (string)ViewState[_usernameStateKey];
else
return _username;
}
set
{
_username = value;
ViewState.Add(_usernameStateKey,value);
}
}
public string Password
{
get
{
if (ViewState[_passwordStateKey] != null)
return (string)ViewState[_passwordStateKey];
else
return _password;
}
set
{
_password = value;
ViewState.Add(_passwordStateKey, value);
}
}
public new void PreRender()
{
EnsureChildControls();
txtusername.Text = ViewState[_usernameStateKey] == null ? _username : (string) ViewState[_usernameStateKey];
txtpassword.Text = ViewState[_passwordStateKey] == null ? _password : (string) ViewState[_passwordStateKey];
}
protected override void CreateChildControls()
{
txtusername = new TextBox();
txtpassword = new TextBox();
cmdLogon = new Button();
reqUsername = new RequiredFieldValidator();
revPassword = new RegularExpressionValidator();
txtusername.ID = "txtusername";
txtpassword.TextMode = TextBoxMode.Password;
cmdLogon.Text = "Logon";
txtusername.Width = 140;
txtpassword.Width = 140;
txtusername.MaxLength = 15;
txtpassword.MaxLength = 15;
txtpassword.TextMode = TextBoxMode.Password;
txtpassword.ID = "txtpassword";
cmdLogon.Text = "Logon";
cmdLogon.Attributes.Add("OnServerClick","Submit_Click");
reqUsername.Display = ValidatorDisplay.Dynamic;
reqUsername.EnableClientScript = true;
reqUsername.ErrorMessage = "Username must not be blank";
reqUsername.ControlToValidate = "txtusername";
revPassword.Display = ValidatorDisplay.Dynamic;
revPassword.EnableClientScript = true;
revPassword.ErrorMessage = "Password must be at least 6 alpha-numeric charactors";
revPassword.ControlToValidate = "txtpassword";
this.Controls.Add(txtusername);
this.Controls.Add(txtpassword);
this.Controls.Add(reqUsername);
this.Controls.Add(revPassword);
}
/// <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)
{
output.Write("<table border=\"1\" width=\"300\" id=\"table1\">");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Username:</td>");
output.Write("<td border=\"0\">");
txtusername.RenderControl(output);
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Password:</td>");
output.Write("<td border=\"0\">");
txtpassword.RenderControl(output);
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\"><td colspan=\"2\"><div align=\"centre\">");
cmdLogon.RenderControl(output);
output.Write("<br>");
reqUsername.RenderControl(output);
output.Write("<br>");
revPassword.RenderControl(output);
output.Write("</div></td></tr>");
output.Write("</table>");
}
}
public class LoginControlDesigner : System.Web.UI.Design.ControlDesigner
{
public override string GetDesignTimeHtml()
{
// Component is the control instance, defined in the base
// designer
LoginControl ctl = (LoginControl) Component;
StringWriter sw = new StringWriter();
HtmlTextWriter output = new HtmlTextWriter(sw);
output.Write("<table border=\"1\" width=\"300\" id=\"table1\">");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Username:</td>");
output.Write("<td border=\"0\">");
//ctl.txtusername.RenderControl(output);
output.Write("txtUsername");
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\">");
output.Write("<td border=\"0\">Password:</td>");
output.Write("<td border=\"0\">");
//ctl.txtpassword.RenderControl(output);
output.Write("txtPassword");
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr border=\"0\"><td colspan=\"2\"><div align=\"centre\">");
//ctl.cmdLogon.RenderControl(output);
output.Write("cmdLogin");
output.Write("<br>");
//ctl.reqUsername.RenderControl(output);
output.Write("<br>");
//ctl.revPassword.RenderControl(output);
output.Write("</div></td></tr>");
output.Write("</table>");
return sw.ToString();
}
}
}
Quotes:
"I am getting better then you guys.." NoteMe, on his leet english skills.
"And I am going to meat her again later on tonight." NoteMe
"I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
"my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
Have I helped you? Please Rate my posts. 
-
Apr 28th, 2005, 08:19 AM
#6
I wonder how many charact
Re: Custom control Properties
Sorry, its INamingContainer.
Code:
public class LoginControl : System.Web.UI.WebControls.WebControl, INamingContainer
As far as the Designer...
see this:
http://www.error-bank.com/microsoft....bl_Thread.aspx
http://www.google.com/search?q=GetDe...&start=10&sa=N
-
Apr 29th, 2005, 06:46 AM
#7
Thread Starter
Not NoteMe
Re: Custom control Properties
Thanks a lot for your continued help.
I've now got the following code, which i think is the c# equivilent of the vb.net stuff in that link you gave. I still get the same result - the control isn't there at design time.
BTW. i'm using MS ASP.NET Web Matrix, not Visual Studio as the designer, would this make a difference?
Code:
public class LoginControlDesigner : System.Web.UI.Design.ControlDesigner
{
protected override string GetEmptyDesignTimeHtml()
{
string HTML = "This is the No.1 Invisible control";
return CreatePlaceHolderDesignTimeHtml(HTML);
}
protected override string GetErrorDesignTimeHtml(Exception e)
{
return CreatePlaceHolderDesignTimeHtml(e.Message + "<br>Check to make sure all properties are valid.");
}
public override string GetDesignTimeHtml()
{
// Component is the control instance, defined in the base
// designer
LoginControl ctl = (LoginControl) Component;
return GetEmptyDesignTimeHtml();
}
}
Quotes:
"I am getting better then you guys.." NoteMe, on his leet english skills.
"And I am going to meat her again later on tonight." NoteMe
"I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
"my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
Have I helped you? Please Rate my posts. 
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|