Wednesday, September 11, 2013

ASP.Net Tutorial Series V


Changing password by providing current password - Part 97

Suggested Videos
Part 94 - Unlocking the locked user accounts
Part 95 - Implementing password reset link
Part 96 - Implementing change password page

In this video we will discuss about, Changing password by providing current password. In real time, users can change their password any time, by providing their current password.



Stored procedure to change password, using their current password
Create Proc spChangePasswordUsingCurrentPassword
@UserName
nvarchar(100),
@CurrentPassword
nvarchar(100),
@NewPassword
nvarchar(100)
as
Begin
 if(Exists(Select Id from tblUsers
    
where UserName = @UserName
    
and [Password] = @CurrentPassword))
 
Begin
  Update tblUsers
 
Set [Password] = @NewPassword
 
where UserName = @UserName
 
 
Select 1 as IsPasswordChanged
 
End
 Else
 Begin
  Select 0 as IsPasswordChanged
 
End
End



ChangePassword.aspx HTML
<div style="font-family: Arial">
<table style="border: 1px solid black">
    <tr>
        <td colspan="2">
            <b>Change Password</b>
        </td>
    </tr>
    <tr id="trCurrentPassword" runat="server">
        <td>
            Current Password
        </td>
        <td>
            :<asp:TextBox ID="txtCurrentPassword" TextMode="Password"
            runat="server"></asp:TextBox>
            <asp:RequiredFieldValidator ID="RequiredFieldValidatorCurrentPassword"
                runat="server" ErrorMessage="Current Password required"
                Text="*" ControlToValidate="txtCurrentPassword" ForeColor="Red">
            </asp:RequiredFieldValidator>
        </td>
    </tr>
    <tr>
        <td>
            New Password
        </td>
        <td>
            :<asp:TextBox ID="txtNewPassword" TextMode="Password"
            runat="server"></asp:TextBox>
            <asp:RequiredFieldValidator ID="RequiredFieldValidatorNewPassword"
                runat="server" ErrorMessage="New Password required"
                Text="*" ControlToValidate="txtNewPassword" ForeColor="Red">
            </asp:RequiredFieldValidator>
        </td>
    </tr>
    <tr>
        <td>
            Confirm New Password
        </td>
        <td>
            :<asp:TextBox ID="txtConfirmNewPassword" TextMode="Password" runat="server">
            </asp:TextBox>
            <asp:RequiredFieldValidator ID="RequiredFieldValidatorConfirmNewPassword"
                runat="server" ErrorMessage="Confirm New Password required" Text="*"
                ControlToValidate="txtConfirmNewPassword"
                ForeColor="Red" Display="Dynamic"></asp:RequiredFieldValidator>
            <asp:CompareValidator ID="CompareValidatorPassword" runat="server"
                ErrorMessage="New Password and Confirm New Password must match"
                ControlToValidate="txtConfirmNewPassword" ForeColor="Red"
                ControlToCompare="txtNewPassword"
                Display="Dynamic" Type="String" Operator="Equal" Text="*">
            </asp:CompareValidator>
        </td>
    </tr>
    <tr>
        <td>
                   
        </td>
        <td>
            &nbsp;<asp:Button ID="btnSave" runat="server"
            Text="Save" onclick="btnSave_Click" Width="70px" />
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <asp:Label ID="lblMessage" runat="server">
            </asp:Label>
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <asp:ValidationSummary ID="ValidationSummary1"
            ForeColor="Red" runat="server" />
        </td>
    </tr>
</table>
</div>

ChangePassword.aspx.cs code:
protected void Page_Load(object sender, EventArgs e)
{
   
if (Request.QueryString["uid"] == null && User.Identity.Name == "")
    {
        Response.Redirect(
"~/Login.aspx");
    }
   
if (!IsPostBack)
    {
       
if (Request.QueryString["uid"] != null)
        {
           
if (!IsPasswordResetLinkValid())
            {
                lblMessage.ForeColor = System.Drawing.
Color.Red;
                lblMessage.Text =
"Password Reset link has expired or is invalid";
            }
            trCurrentPassword.Visible =
false;
        }
       
else if (User.Identity.Name != "")
        {
            trCurrentPassword.Visible =
true;
        }
    }
}

protected void btnSave_Click(object sender, EventArgs e)
{
   
if ((Request.QueryString["uid"] != null && ChangeUserPassword()) ||
        (User.Identity.Name != "" && ChangeUserPasswordUsingCurrentPassword()))
    {
        lblMessage.Text =
"Password Changed Successfully!";
    }
   
else
    {
        lblMessage.ForeColor = System.Drawing.
Color.Red;
       
if (trCurrentPassword.Visible)
        {
            lblMessage.Text =
"Invalid Current Password!";
        }
       
else
        {
            lblMessage.Text =
"Password Reset link has expired or is invalid";
        }
    }
}

private bool ExecuteSP(string SPName, List<SqlParameter> SPParameters)
{
   
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
   
using (SqlConnection con = new SqlConnection(CS))
    {
       
SqlCommand cmd = new SqlCommand(SPName, con);
        cmd.CommandType =
CommandType.StoredProcedure;

       
foreach (SqlParameter parameter in SPParameters)
        {
            cmd.Parameters.Add(parameter);
        }

        con.Open();
        return
Convert.ToBoolean(cmd.ExecuteScalar());
    }
}

private bool IsPasswordResetLinkValid()
{
   
List<SqlParameter> paramList = new List<SqlParameter>()
    {
       
new SqlParameter()
        {
            ParameterName =
"@GUID",
            Value = Request.QueryString[
"uid"]
        }
    };

   
return ExecuteSP("spIsPasswordResetLinkValid", paramList);
}

private bool ChangeUserPassword()
{
   
List<SqlParameter> paramList = new List<SqlParameter>()
    {
       
new SqlParameter()
        {
            ParameterName =
"@GUID",
            Value = Request.QueryString[
"uid"]
        },
       
new SqlParameter()
        {
            ParameterName =
"@Password",
            Value =
FormsAuthentication.HashPasswordForStoringInConfigFile(txtNewPassword.Text, "SHA1")
        }
    };

   
return ExecuteSP("spChangePassword", paramList);
}

private bool ChangeUserPasswordUsingCurrentPassword()
{
   
List<SqlParameter> paramList = new List<SqlParameter>()
    {
       
new SqlParameter()
        {
            ParameterName =
"@UserName",
            Value = User.Identity.Name
        },
       
new SqlParameter()
        {
            ParameterName =
"@CurrentPassword",
            Value =
FormsAuthentication.HashPasswordForStoringInConfigFile(txtCurrentPassword.Text, "SHA1")
        },
       
new SqlParameter()
        {
            ParameterName =
"@NewPassword",
            Value =
FormsAuthentication.HashPasswordForStoringInConfigFile(txtNewPassword.Text, "SHA1")
        }
    };

   
return ExecuteSP("spChangePasswordUsingCurrentPassword", paramList);
}

 


Unlocking the locked user accounts using a web page - Part 98

Suggested Videos
Part 95 - Implementing password reset link
Part 96 - Implementing change password page
Part 97 - Changing password by providing current password

If a user repeatedly enters the wrong password. The accounts are locked to prevent hackers from guessing passwords and making dictionary attacks. In Part 94, of this video series we have discussed about un-locking user accounts, using a SQL Server agent job.  
Please watch Part 94, before proceeding with this video.



In this video, we will discuss about unlocking the locked user accounts, using a web page that lists all the locked user accounts. From this page, the help desk agent, can unlock the account by clicking a button. This is not as dangerous as running a manual update query, but still a manual process and may be in-efficient.

Stored procedure to get the information about, all the locked user accounts.
Create proc spGetAllLocakedUserAccounts
as
Begin
 Select UserName, Email, LockedDateTime,
 
DATEDIFF(hour, LockedDateTime, GETDATE()) as HoursElapsed
 
from tblUsers
 
where IsLocked = 1
End



Add a webform, with name "AccessDenied.aspx".
<div style="font-family:Arial;">
    <h1 style="color:Red">Access Denied</h1>
</div>

Add a webform, with name "LockedAccounts.aspx". Copy and paste the following HTML on this page.
<div style="font-family:Arial">
    <asp:GridView ID="gvLockedAccounts" runat="server" AutoGenerateColumns="False">
        <Columns>
            <asp:BoundField DataField="UserName" HeaderText="User Name" />
            <asp:BoundField DataField="Email" HeaderText="Email" />
            <asp:BoundField DataField="LockedDateTime"
                HeaderText="Locked Date &amp; Time" />
            <asp:BoundField DataField="HoursElapsed" HeaderText="Hours Elapsed" >
            <ItemStyle HorizontalAlign="Center" />
            </asp:BoundField>
            <asp:TemplateField HeaderText="Enable">
                <ItemTemplate>
                    <asp:Button ID="btnEnable" runat="server" Text="Enable"
                    Enabled='<%#Convert.ToInt32(Eval("HoursElapsed")) > 24%>'/>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</div>

"LockedAccounts.aspx.cs" code
protected void Page_Load(object sender, EventArgs e)
{
   
if (User.Identity.Name.ToLower() == "test")
    {
       
if (!IsPostBack)
        {
            GetData();
        }
    }
   
else
    {
        Response.Redirect(
"~/AccessDenied.aspx");
    }
}

private void GetData()
{
   
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
   
using (SqlConnection con = new SqlConnection(CS))
    {
       
SqlCommand cmd = new SqlCommand("spGetAllLocakedUserAccounts", con);
        cmd.CommandType =
CommandType.StoredProcedure;

        con.Open();
        gvLockedAccounts.DataSource = cmd.ExecuteReader();
        gvLockedAccounts.DataBind();
    }
}

Implementing Enable button to unlock user accounts - Part 99

Suggested Videos
Part 96 - Implementing change password page
Part 97 - Changing password by providing current password
Part 98 - Unlocking the locked user accounts using a web page

This is continuation to Part 98. To implement, the "Enable" button, make the following changes to the gridview control.



First Change: Specify the CommandArgument attribute of the Button control in the Template column.
<asp:TemplateField HeaderText="Enable">
    <ItemTemplate>
        <asp:Button ID="btnEnable" runat="server" CommandArgument='<%# Eval("UserName") %>'
        Text="Enable" Enabled='<%#Convert.ToInt32(Eval("HoursElapsed")) > 24%>'/>
    </ItemTemplate>
</asp:TemplateField>



Second Change: Generate the "RowCommand" event handler for the GridView control.
1. Right Click on the GridView Control and Select properties.
2. In the "Properties Window", click on events icon.
3. In the events windows, double click on the text box next to "Row Command" event.

With these 2 changes the HTML of the "LockedAccounts.aspx" should look as shown below.
<div style="font-family: Arial">
<asp:GridView ID="gvLockedAccounts" runat="server" AutoGenerateColumns="False"
    OnRowCommand="gvLockedAccounts_RowCommand">
    <Columns>
        <asp:BoundField DataField="UserName" HeaderText="User Name" />
        <asp:BoundField DataField="Email" HeaderText="Email" />
        <asp:BoundField DataField="LockedDateTime" HeaderText="Locked Date &amp; Time" />
        <asp:BoundField DataField="HoursElapsed" HeaderText="Hours Elapsed">
            <ItemStyle HorizontalAlign="Center" />
        </asp:BoundField>
        <asp:TemplateField HeaderText="Enable">
            <ItemTemplate>
                <asp:Button ID="btnEnable" CommandArgument='<%# Eval("UserName") %>' runat="server"
                    Text="Enable" Enabled='<%#Convert.ToInt32(Eval("HoursElapsed")) > 24%>' />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
</div>

Copy and paste the following private method in "LockedAccounts.aspx.cs" page.
private void EnableUserAccount(string UserName)
{
   
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
   
using (SqlConnection con = new SqlConnection(CS))
    {
       
SqlCommand cmd = new SqlCommand("spEnableUserAccount", con);
        cmd.CommandType =
CommandType.StoredProcedure;

       
SqlParameter paramUserName = new SqlParameter()
        {
            ParameterName =
"@UserName",
            Value = UserName
        };

        cmd.Parameters.Add(paramUserName);

        con.Open();
        cmd.ExecuteNonQuery();
    }
}

Invoke EnableUserAccount() method, in RowCommand() event handler as shown below.
protected void gvLockedAccounts_RowCommand(object sender, GridViewCommandEventArgs e)
{
    EnableUserAccount(e.CommandArgument.ToString());
    GetData();
}

Secure Socket Layer in asp.net - Part 100

Suggested Videos
Part 97 - Changing password by providing current password
Part 98 - Unlocking the locked user accounts using a web page
Part 99 - Implementing Enable button to unlock user accounts

In this video we will discuss about 
1. The advantage of using HTTPS over HTTP protocol
2. How to identify, if the web application i am accessing, use HTTPS protocol
3. How to configure HTTPS instead of HTTP for asp.net web applications
4. What is SSL or Secure Socket Layer and how is it different from HTTPS
5. Who issues server certificates and can't I generate test certificates
6. What about performance when using HTTPS over HTTP



Advantages of using HTTPS
HTTP stands for Hyper Text Transfer Protocol. HTTPS, stands for Hyper Text Transfer Protocol Secure. As the name suggests, HTTPS is more secure than HTTP. When the web server and the client communicate, using HTTP, protocol, the messages that are exchanged over the internet are not encrypted. Any one can secretly listen and see the messages that are exchanged between the client and the web server. That's why, any sensitive information like passwords, financial transactions should never be done over HTTP protocol. Most of the banking applications use HTTPS protocol. Messages exchanged between the client and web server, using the HTTPS protocol are encrypted and are very secure. HTTP use port 80 and HTTPS use port 443.



How to identify, if the web application i am accessing, use HTTPS protocol
There are 2 ways
1. Browser displays a LOCK symbol either in the address or status bar. Click on the lock icon, for more information like, the certificate issuing authority, encryption key length etc.
2. In the address bar look for HTTPS instead of HTTP

How to configure HTTPS instead of HTTP for asp.net web applications
IIS is the web server for asp.net web applications. so the configuration to use HTTPS, is usually done in IIS. The encryption and decryption of  messages exchanged between the client and the server is done by server certificates. These server certificates needs to be installed on the IIS server. We will discuss about IIS configuration in a later video session.

What is Secure Socket Layer and how is it different from HTTPS
HTTPS is HTTP (HyperText Transfer Protocol) plus SSL (Secure Socket Layer). SSL standing for Secure Sockets Layer (SSL) is a standard security technology for establishing an encrypted link between a web server and a browser, so that the data sent over the Internet can’t be read by others. When a user requests a secure Web page, the server generates an encryption key for the user’s session and then encrypts the page’s data before sending a response. On the client side, the browser uses that same encryption key to decrypt the requested Web page and to encrypt new requests sent from that page. SSL uses server certificates for encryption and decryption. An SSL certificate contains a public key and certificate issuer. Not only can clients use the certificate to communicate with a server, clients can verify that the certificate was cryptographically signed by an official Certificate Authority. For example, if your browser trusts the VeriSign Certificate Authority, and VeriSign signs my SSL certificate, your browser will inherently trust my SSL certificate.

Who issues server certificates and can't I generate test certificates
Server certificates are issued by an entity called certificate authority. There are several trusted certificate authorities like
1. verisign
2. Thawte
3. Geotrust
4. Comodo
5. GoDaddy

The certificate authority acts as a clearing house to verify the server’s identity over the Internet. When a browser requests a page over https, the browser also, requests the server certificate and checks it against a list of trusted sites provided by the certificate authority. If the server certificate does not match one of the sites already authorized by the user, or if the server certificate does not match the Web address for which it was registered, or if there are any other problems with the server certificate, a warning message is displayed. The warning message from internet explorer is shown below.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9jmJsDWRVpMSpchYoD-xvn_af9L7uLqaJBeJ385UJywqBbAerjbRUTFAGM3BHygGmYuvUgcGNwYerIlig5265B6Mk65tdvnqRlZMLGvQl4yztqTsELmKpnD1D5OLE9-fynToYallBYoGJ/s1600/server+certificate+error.gif

Besides providing encryption and decryption for secure data transmission, certificate authority also provides assurance to users that a website is authentic.

It is also possible to generate our own server certificates, using a tool called makecert.exe. This tool comes with visual studio and can be used from visual studio command prompt. The certificates that are generated using this tool, can only be used for testing purposes and not for production use. We will discuss about generating and installing server certificates in our next video session.

What about performance when using HTTPS over HTTP
Extra processing time is required for HTTPS, for key negotiation. Key negotiation is also termed as SSL handshake.  The handshake allows the server to authenticate itself to the client.

Implementing SSL in asp.net web application - Part 101

Suggested Videos
Part 98 - Unlocking the locked user accounts using a web page
Part 99 - Implementing Enable button to unlock user accounts
Part 100 - Secure Socket Layer in asp.net

In this video we will discuss about
1. Understand the term self-signed certificates
2. Creating self-signed certificates
3. Configuring an asp.net web application to use SSL, that is use HTTPS instead of HTTP
4. Importing and exporting certificates



What are self signed certificates
A self-signed certificate is an identity certificate that is signed by its own creator. Certificates are signed by Certificate Authority. In general self signed certificates are fine for testing purposes and not for production use.

Creating self-signed certificates
There are several ways to create self signed test certificates. Let us explore 2 of the easier options available. The easiest and simpler approach is to use IIS to create these certificates. In IIS 7.5
1. Click on the "Server Name"
2. Double click "Server Certificates" feature
3. Click on "Create Self Signed Certificate" link, under "Actions"
4. Specify a friendly name for the certificate and click OK. The friendly name is not part of the certificate itself, but is used by the server administrator to easily distinguish the certificate.



The generated test certificate, is also automatically installed into the certificate store.

MakeCert.exe tool can be used as another way to generate, test certificates. The following link from microsoft explains, various options that can be used with this tool. This is a command line tool and must be run from visual studio command prompt.
http://msdn.microsoft.com/en-us/library/bfsktky3.aspx

Makecert -r -pe -n "CN=YourComputerName" -b 01/01/2000 -e 01/01/2100 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

Note: Replace YourComputerName, with the name of your computer.

Associating an asp.net web application with a specific certificate
Add HTTPS site binding, if it is not already present
1. Open IIS
2. Expand the "Server Name"
3. Expand "Sites"
4. Select "Default Web Site"
5. Click "Binding" under "Edit Site" in "Actions" pane.
6. In the "Site Bindings" window, Click "Add"
7. Select Type = "https" and the SSL Certificate and click "OK"
8. Click "Close" on "Site Bindings" window

At this point, you will be able to access your application using both HTTP and HTTPS protocol. When the site is accessed over HTTPS, you may receive a browser warning about the authenticity of the website. In a later video session we will discuss about resolving this.

If you want to dis-allow, access over HTTP protocol there are 2 ways
First Way: Remove HTTP binding at the IIS Server level. This option will prevent all the web applications, running on that server to use only HTTPS binding.

Second Way: Let both the bindings be available at the server level and configure SSL settings at an application or web site level.
1. Select your web application in IIS
2. Double click "SSL Settings" from the features window
3. Make sure "Require SSL" check box is checked.
4. Click "Apply" under "Actions" pane

Now, if you try to access the application using HTTP instead of HTTPS, you will get an error
HTTP Error 403.4 - Forbidden
The page you are trying to access is secured with Secure Sockets Layer (SSL)

Use Import and Export feature of IIS to import and export certificates

Redirect http to https in IIS - Part 102

Suggested Videos
Part 99 - Implementing Enable button to unlock user accounts
Part 100 - Secure Socket Layer in asp.net
Part 101 - Implementing SSL in asp.net web application

In this video we will discuss about redirecting users from HTTP to HTTPS. In the previous session, we discussed about implementing SSL in asp.net.
Please watch Part 101, before proceeding with this video.



To redirect users from HTTP to HTTPS automatically, there are several ways. In this video we will discuss about using "url rewrite" module. There are 3 simple steps

Step 1:
Please download and install "URL ReWrite" module from the following link.
http://www.iis.net/downloads/microsoft/url-rewrite

Step 2:
Uncheck "Require SSL" option from "SSL Settings" for the web application in IIS.



Step 3:
Copy and paste the following in the root web.config file of your application.
<system.webServer>
    <httpRedirect enabled="false" destination="" httpResponseStatus="Found" />
    <rewrite>
        <rules>
            <rule name="HTTP to HTTPS Redirection" stopProcessing="true">
                <match url="(.*)" />
                <conditions>
                    <add input="{HTTPS}" pattern="off" />
                </conditions>
                <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Found" />
            </rule>
        </rules>
    </rewrite>
</system.webServer>

Now try to navigate to the application using HTTP, you will automatically be redirected to HTTPS.

These rules can also be created in IIS directly using the "URL Rewrite" module

In the next video we will discuss about using "IIS Error Pages" to redirect users from HTTP to HTTPS automatically.

Redirect http to https in IIS using custom errors - Part 103

Suggested Videos
Part 100 - Secure Socket Layer in asp.net
Part 101 - Implementing SSL in asp.net web application
Part 102 - Redirect http to https in IIS

In this video we will discuss about redirecting users from HTTP to HTTPS, using "IIS Error Pages". In the previous session, we discussed about redirecting users using "URL ReWrite" module. 



Custom error pages can be set at the server level or at a specific application level in IIS. In this demo, we will discuss about setting custom error pages at the server level. There are 3 simple steps.

Step 1: 
Make sure "Require SSL" option from "SSL Settings" is checked for your web application in IIS. Now, browse the web site, using HTTP, and you will receive the following error. Pay attention to HTTP error code - 403.4, which we will be using later.
HTTP Error 403.4 - Forbidden
The page you are trying to access is secured with Secure Sockets Layer (SSL).



Step 2:
Copy and paste the following HTML in a notepad and save it as "RedirectToHttps.htm" in "C:\inetpub".
<html>
<head>
   <title>
      Redirecting to HTTPS
   </title>
</head>
<script language="JavaScript">
function redirectHttpToHttps()
{
    var httpURL= window.location.hostname + window.location.pathname;
    var httpsURL= "https://" + httpURL;
    window.location = httpsURL;
}
redirectHttpToHttps();
</script>
<body>
</body>
</html>

Step 3:
1. In IIS, select the "Server Name" and double click "Error Pages" to open the feature.
2. Click on "Add" link under "Actions"
3. Set Status Code = 403.4, File Path = C:\Inetpub\RedirectToHttps.htm and click "OK"
4. Now click "Edit Feature Settings" link under "Actions"
5. Select "Custom Error Pages" and Path = C:\inetpub\RedirectToHttps.htm

Now, access the application using HTTP. You will be automatically redirected to HTTPS.

User controls in asp.net - Part 104

Suggested Videos
Part 101 - Implementing SSL in asp.net web application
Part 102 - Redirect http to https in IIS
Part 103 - Redirect http to https in iis using custom errors

Web user controls combine one or more server or HTML controls on a Web user control page, which can, in turn, be used on a Web form as a single control. For example, to capture dates from the end user on a webform, we need a TextBox, ImageButton and, a Calendar control. A web form to capture date of birth is shown below in the image.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimkFMtq6kuZrinCdq6yWjSGYpSFO82GtetwlGW6Bh1RinRx5Lht8j8_slpcxzyrqMGXNZMCzWlkcfYMt9sANFUSpfoqKdaoM4T-Sw065douDMJW7ot1WA-quyj6y6sJPnOb2v4BM-v8dOq/s1600/User+controls+in+asp.net.png



To select the date
1. User clicks on the calendar image.
2. The Calendar control becomes visible.
3. User selects a date from the calendar.
4. Textbox control is automatically populated with the selected date and the calendar becomes invisible.



To achieve this functionality, considerable amount of code needs to be written in the webform.
We discussed about this in Part 32 of the asp.net video series.

If, I am capturing dates, on multiple web forms, rather than repeating the same HTML mark up and code, on each and every web form, we can encapsulate everything into a single web user control, which in turn, can be used on multiple web forms. This way we are reusing the same code, which saves a lot of time in terms of development and testing. So in short, user controls, increase re-usability of code, implement encapsulation and reduce development and maintenance time.

Designing and implementing web user controls is very similar to web forms.Web forms, have the extension of .aspx, where as web user controls have the extension of .ascx. Webforms begin with @Page directive and can have <html>, <head>, and <body> elements, where as a web user controls begin with @ Control directive and cannot have html, head, and body elements. Just, like webforms, user controls also have code behind files.

In this demo, we will create a custom calendar user control, that can be reused on multiple webforms. To create a user control
1. Right click on the web application project in solution explorer
2. Select Add >> New Item
3. From the "Add New Item" dialog box, select "Web User Control"
4. Set Name = CalendarUserControl
5. Click on "Add"

Notice that, CalendarUserControl.ascx page is created. Copy and paste the following HTML.
<asp:TextBox ID="txtDate" runat="server" Width="115px"></asp:TextBox>
<asp:ImageButton ID="ImgBtn" runat="server"
    ImageUrl="~/Images/Calendar.png" onclick="ImgBtn_Click" />
<asp:Calendar ID="Calendar1" runat="server" onselectionchanged="Calendar1_SelectionChanged">
</asp:Calendar>

CalendarUserControl.ascx.cs code
public partial class CalendarUserControl : System.Web.UI.UserControl
{
   
protected void Page_Load(object sender, EventArgs e)
    {
       
if (!IsPostBack)
        {
            Calendar1.Visible =
false;
        }
    }

   
protected void ImgBtn_Click(object sender, ImageClickEventArgs e)
    {
       
if (Calendar1.Visible)
        {
            Calendar1.Visible =
false;
        }
       
else
        {
            Calendar1.Visible =
true;
        }
    }

   
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
    {
        txtDate.Text = Calendar1.SelectedDate.ToShortDateString();
        Calendar1.Visible =
false;
    }
}

We are done creating the calendar user control. In the next video, we will discuss about using this calendar control on a web form

Adding and using user controls on a webform - Part 105

Suggested Videos
Part 102 - Redirect http to https in IIS
Part 103 - Redirect http to https in iis using custom errors
Part 104 - Creating user controls

In the previous video, we discussed about creating a calendar user control. Please watch Part 104, before proceeding with this video. In this video we will discuss about
1. Adding and using user controls on a webform
2. Adding properties to the user control



Adding and using user controls on a webform
Adding user controls to a web page is very straight forward. Simply drag the user control from solution explorer and drop it on the web page. Make sure, the "Design" view of the webform is selected before dragging and dropping the user control on the webform. This will automatically,
1. Add a "Register" directive for the user control and
2. The control declaration



"Register" directive for the CalendarUserControl
<%
@ Register src="CalendarUserControl.ascx" tagname="CalendarUserControl" tagprefix="uc1" %>

Control declaration for the CalendarUserControl
<uc1:CalendarUserControl ID="CalendarUserControl1" runat="server" />

Notice, the "tagprefix" and "tagname" in the "Register" directive. These are used in the control declaration. For asp.net controls, the "tagprefix" is "asp". Tagprefix, can be changed, if you wish to do so.

If you intend to add the user control on multiple web forms, rather than including the "Register" directive on each and every web form, every time, the control can be registered once in web.config file and can be used on any number of web forms, without the "Register" directive.
<system.web>
  
<pages>
    
<controls>
      
<add src="~/CalendarUserControl.ascx" tagName="CalendarUserControl" tagPrefix="uc1"/>
    
</controls>
  
</pages>
</system.web>

At this point, you get the following error, if both, the user control and the webform are in the same directory. This limitation is by design due to an internal design consideration for performance.
The page '/WebForm2.aspx' cannot use the user control '/CalendarUserControl.ascx', because it is registered in web.config and lives in the same directory as the page.

To solve this error move the user control to a different folder, and update the "src" attribute of the "Register" directive in web.config file accordingly.

Adding properties to the user control:
A user control can also have it's own properties and methods. At the moment, CalendarUserControl does not expose any property that returns the selected date.

For example, drag and drop a button control on the same webform. when I click this button, we want to print the selected date. To do this let's add the following SelectedDate property for the CalendarUserControl.
public string SelectedDate
{
   
get
    {
       
return txtDate.Text;
    }
   
set
    {
        txtDate.Text =
value;
    }
}

On the webform, in the button click event, I should now be able to retrieve, the selected date using "SelectedDate" property of the "CalendarUserControl" as shown below.
protected void Button1_Click(object sender, EventArgs e)
{
    Response.Write(CalendarUserControl1.SelectedDate);
}

You can also set this property declaratively in the HTML at design time as shown below. When this webform, loads, it shows the date, that we have set.
<uc1:CalendarUserControl SelectedDate="01/01/2013" ID="CalendarUserControl1" runat="server" />

But one limitation, here with the user control, is that the design time value is not shown in the control at design time. This is by design, and there are 2 ways to solve this issue.
1. Create a custom control instead of user control.
2. Compile the user control into a DLL.

We will be discussing about these in later video sessions.

In the next video session we will discuss about adding "events" to our "CalendarUserControl"

Raising custom events from user controls - Part 106

Suggested Videos
Part 103 - Redirect http to https in iis using custom errors
Part 104 - Creating user controls
Part 105 - Using user controls on a webform

In this video we will discuss about 
1. Adding events to UserControls
2. Events and delegates



Most people feel "events and delegates" are complex and difficult to understand. Events and delegates are not that complex to understand, if the basics are right. To get the most out of this video, I strongly recommend to
watch parts 36, 37 , 38 and 39 from C# Video series, and parts 104 and 105 from asp.net video series, before proceeding with this video.

Very important points to keep in mind, when understanding "Events and Delegates"
1. Delegates are function pointers, and their syntax is very similar to that of a function.
2. Events are variables of type delegates with an event keyword.
If these points are not clear at the moment, don't worry, they will be much clear as we progress.



At the moment, the CalendarUserControl does not have any custom events. Let us say, we want to raise CalendarVisibilityChanged event every time the visibility of the calendar changes. The visibility of the calendar is toggled by clicking on the image button.

The following are the steps to raise CalendarVisibilityChanged event from the CalendarUserControl
Step 1: Create CalendarVisibilityChangedEventArgs class that will contain the event data.
public class CalendarVisibilityChangedEventArgs : EventArgs
{
   
private bool _isCalendarVisible;

    // Constructor to initialize event data
   
public CalendarVisibilityChangedEventArgs(bool isCalendarVisible)
    {
       
this._isCalendarVisible = isCalendarVisible;
    }

   
// Returns true if the calendar is visible otherwise false
   
public bool IsCalendarVisible
    {
       
get
        {
           
return this._isCalendarVisible;
        }
    }
}

Step 2: Create CalendarVisibilityChangedEventHandler delegate. "sender" is the reference variable that points to the instance of the CalendarUserControl, that raises this event. "CalendarVisibilityChangedEventArgs" object will contain "CalendarVisibilityChanged" event data.
public delegate void CalendarVisibilityChangedEventHandler(object sender, CalendarVisibilityChangedEventArgs e);

Step 3: Create CalendarVisibilityChanged event. Remember that, an event is a variable of type delegate. In the line below, we are just creating a variable "CalendarVisibilityChanged" of type "CalendarVisibilityChangedEventHandler" with delegate keyword in front of it.
public event CalendarVisibilityChangedEventHandler CalendarVisibilityChanged;

Step 4: Create a protected virtual method to raise the event. Since this method is protected and virtual, all classes deriving from the CalendarUserControl class can overridde this method, if they wish to do so. This method enables the derived classes to do some additional work before the event can be raised. Just before raising the event, we are checking if CalendarVisibilityChanged is null. If you are not sure about this, please don't worry. This will be much clear in the next video session, when we discuss about consuming CalendarVisibilityChanged event.
protected virtual void OnCalendarVisibilityChanged(CalendarVisibilityChangedEventArgs e)
{
   
if (CalendarVisibilityChanged != null)
    {
        CalendarVisibilityChanged(
this, e);
    }
}

For example, if we have a class "DerivedCalendarUserControl" that derives from CalendarUserControl class. "DerivedCalendarUserControl" can override the virtual "OnCalendarVisibilityChanged()" method as shown below. "CalendarVisibilityChanged" will only be raised when "base.OnCalendarVisibilityChanged(e);" is invoked. So, using a "protected virtual" method to raise events is a very useful technique.
public class DerivedCalendarUserControl : CalendarUserControl
{
   
// Other methods, properties etc..
   
   
protected override void OnCalendarVisibilityChanged(CalendarVisibilityChangedEventArgs e)
    {
        // Do some additional work before raising the event
        base.OnCalendarVisibilityChanged(e);
    }
}

Step 5: Finally raise the event, whenever the visibility of the Calendar is changed in the CalendarUserControl. The calendar visibility is changed, whenevr the user clicks on the image button and when the date in the calendar is selected. So, raise "CalendarVisibilityChanged" event from ImgBtn_Click() and Calendar1_SelectionChanged(). Before raising the event, create and instance of "CalendarVisibilityChangedEventArgs" and pass event data, that is "true" or "false" to the contrustor of this class.
protected void ImgBtn_Click(object sender, ImageClickEventArgs e)
{
   
if (Calendar1.Visible)
    {
        Calendar1.Visible =
false;
       
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData =
           
new CalendarVisibilityChangedEventArgs(false);
        OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
    }
   
else
    {
               
        Calendar1.Visible =
true;
       
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData =
           
new CalendarVisibilityChangedEventArgs(true);
        OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
    }
}

protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
    txtDate.Text = Calendar1.SelectedDate.ToShortDateString();
    Calendar1.Visible =
false;
   
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData =
       
new CalendarVisibilityChangedEventArgs(false);
    OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
}

Here is the complete CalendarUserControl code
public partial class CalendarUserControl : System.Web.UI.UserControl
{
   
protected void Page_Load(object sender, EventArgs e)
    {
       
if (!IsPostBack)
        {
            Calendar1.Visible =
false;
        }
    }

   
protected void ImgBtn_Click(object sender, ImageClickEventArgs e)
    {
       
if (Calendar1.Visible)
        {
            Calendar1.Visible =
false;
           
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData =
               
new CalendarVisibilityChangedEventArgs(false);
            OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
        }
       
else
        {
               
            Calendar1.Visible =
true;
           
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData =
               
new CalendarVisibilityChangedEventArgs(true);
            OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
        }
    }

   
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
    {
        txtDate.Text = Calendar1.SelectedDate.ToShortDateString();
        Calendar1.Visible =
false;
       
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData =
           
new CalendarVisibilityChangedEventArgs(false);
        OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
    }

   
public string SelectedDate
    {
       
get
        {
           
return txtDate.Text;
        }
       
set
        {
            txtDate.Text =
value;
        }
    }
       
   
public event CalendarVisibilityChangedEventHandler CalendarVisibilityChanged;

   
protected virtual void OnCalendarVisibilityChanged(CalendarVisibilityChangedEventArgs e)
    {
       
if (CalendarVisibilityChanged != null)
        {
            CalendarVisibilityChanged(
this, e);
        }
    }
}

public class CalendarVisibilityChangedEventArgs : EventArgs
{
   
private bool _isCalendarVisible;

   
// Constructor to initialize event data
   
public CalendarVisibilityChangedEventArgs(bool isCalendarVisible)
    {
       
this._isCalendarVisible = isCalendarVisible;
    }

   
// Returns true if the calendar is visible otherwise false
   
public bool IsCalendarVisible
    {
       
get
        {
           
return this._isCalendarVisible;
        }
    }
}

public delegate void CalendarVisibilityChangedEventHandler(object sender, CalendarVisibilityChangedEventArgs e);

Consuming user control custom events - Part 107

Suggested Videos
Part 104 - Creating user controls
Part 105 - Using user controls on a webform
Part 106 - Raising custom events from user controls

In Part 106 of this video series, we discussed about raising custom events from a user control. Please watch part 106, before proceeding. 



In this video, we will discuss about 
1. Consuming custom events of the user control
2. Understanding the importance of, checking if the event is null, before raining the event. We skipped discussing this, when we were discussing about raising custom events in Part 106.
protected virtual void OnCalendarVisibilityChanged(CalendarVisibilityChangedEventArgs e)
{
   
// NULL check
   
if (CalendarVisibilityChanged != null)
    {
        CalendarVisibilityChanged(
this, e);
    }
}



Consuming custom event "CalendarVisibilityChanged"
To consume the event, there are 2 simple steps.
Step 1:
Create an event handler method as shown below. The method signature must match the signature of the "CalendarVisibilityChangedEventHandler" delegate. Notice that, in the event handler method, we are retrieving event data using "IsCalendarVisible" property.
protected void CalendarUserControl1_CalendarVisibilityChanged(object sender, CalendarVisibilityChangedEventArgs e)
{
    Response.Write(
"Calendar Visible = " + e.IsCalendarVisible.ToString());
}

Step 2: Register event handler method "CalendarUserControl1_CalendarVisibilityChanged()" with "CalendarVisibilityChanged" events of the "CalendarUserControl" using "+=" as shown below. Do this, in the Page_load() event of "WebForm1". To unregister we can use "-=".
protected void Page_Load(object sender, EventArgs e)
{
    CalendarUserControl1.CalendarVisibilityChanged +=
       
new CalendarVisibilityChangedEventHandler(CalendarUserControl1_CalendarVisibilityChanged);
}

That's it. Run the project and click on the calendar image to toggle the display, the custom event will be raised and handled. You should see a message "Calendar Visible = true" or "Calendar Visible =  false" depending on the visibility of the calendar control.

Understanding the importance of, checking if the event is null, before raising the event
Now comment the line that registers event handler method in the Page_Load() event. Run the application and click on the image button. Nothing happens and also we don't get any run time errors.

Now comment the line that checks for null in "OnCalendarVisibilityChanged()" method as shown below.
protected virtual void OnCalendarVisibilityChanged(CalendarVisibilityChangedEventArgs e)
{
   
// NULL check
    //if (CalendarVisibilityChanged != null)
    //{
        CalendarVisibilityChanged(this, e);
   
//}
}

Run the application and click on the image button. You should get a "NullReferenceException". The exception is due to CalendarVisibilityChanged() being null. So, if there are no subscribers for the event, that is, if there are no event handler methods registered with CalendarVisibilityChanged event, and if we try to raise the event, we get the exception. To avoid this it is always better to check for null, before raising the event. 

Events and delegates in c# - Part 108

Suggested Videos
Part 105 - Using user controls on a webform
Part 106 - Raising custom events from user controls
Part 107 - Consuming user control custom events

In this video we will discuss about raising another custom event from CalendarUserControl. If you have not watched Parts 106 and 107, I would strongly encourage you to do so before continuing with this video. In this part, we will discuss about raising DateSelected custom event, whenever, the user selects a "Date" from the "CalendarUserControl".



The following are the steps to raise this event
Step 1: Create "DateSelectedEventArgs" class that will contain the event data.
public class DateSelectedEventArgs : EventArgs
{
   
private DateTime _selectedDate;

   
public DateSelectedEventArgs(DateTime selectedDate)
    {
       
this._selectedDate = selectedDate;
    }

   
public DateTime SelectedDate
    {
       
get
        {
           
return this._selectedDate;
        }
    }
}



Step 2: Create DateSelectedEventHandler delegate.
public delegate void DateSelectedEventHandler(object sender, DateSelectedEventArgs e);

Step 3: Create DateSelected event. 
public event DateSelectedEventHandler DateSelected;

Step 4: Create a protected virtual method "OnDateSelection" to raise the event.
protected virtual void OnDateSelection(DateSelectedEventArgs e)
{
   
if (DateSelected != null)
    {
        DateSelected(
this, e);
    }
}

Step 5: Finally raise the event, whenever a date is selected from the CalendarUserControl. 
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
    txtDate.Text = Calendar1.SelectedDate.ToShortDateString();
   
DateSelectedEventArgs dateSelectedEventData = new DateSelectedEventArgs(Calendar1.SelectedDate);
    OnDateSelection(dateSelectedEventData);

   
// Rest of the code
}

Finally, here is the complete CalendarUserControl code, with both the custom events. 
1. "DateSelected" event
2. "CalendarVisibilityChanged" event

public partial class CalendarUserControl : System.Web.UI.UserControl
{
   
protected void Page_Load(object sender, EventArgs e)
    {
       
if (!IsPostBack)
        {
            Calendar1.Visible =
false;
        }
    }

   
protected void ImgBtn_Click(object sender, ImageClickEventArgs e)
    {
       
if (Calendar1.Visible)
        {
            Calendar1.Visible =
false;
           
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData =
               
new CalendarVisibilityChangedEventArgs(false);
            OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
        }
       
else
        {

            Calendar1.Visible =
true;
           
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData = new CalendarVisibilityChangedEventArgs(true);
            OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
        }
    }

   
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
    {
        txtDate.Text = Calendar1.SelectedDate.ToShortDateString();
       
DateSelectedEventArgs dateSelectedEventData = new DateSelectedEventArgs(Calendar1.SelectedDate);
        OnDateSelection(dateSelectedEventData);

        Calendar1.Visible =
false;
       
CalendarVisibilityChangedEventArgs calendarVisibilityChangedEventData = new CalendarVisibilityChangedEventArgs(false);
        OnCalendarVisibilityChanged(calendarVisibilityChangedEventData);
    }

   
public string SelectedDate
    {
       
get
        {
           
return txtDate.Text;
        }
       
set
        {
            txtDate.Text =
value;
        }
    }

   
public event DateSelectedEventHandler DateSelected;

   
public event CalendarVisibilityChangedEventHandler CalendarVisibilityChanged;

   
protected virtual void OnCalendarVisibilityChanged(CalendarVisibilityChangedEventArgs e)
    {
       
if (CalendarVisibilityChanged != null)
        {
            CalendarVisibilityChanged(
this, e);
        }
    }

   
protected virtual void OnDateSelection(DateSelectedEventArgs e)
    {
       
if (DateSelected != null)
        {
            DateSelected(
this, e);
        }
    }
}

public class DateSelectedEventArgs : EventArgs
{
   
private DateTime _selectedDate;

   
public DateSelectedEventArgs(DateTime selectedDate)
    {
       
this._selectedDate = selectedDate;
    }

   
public DateTime SelectedDate
    {
       
get
        {
           
return this._selectedDate;
        }
    }
}

public class CalendarVisibilityChangedEventArgs : EventArgs
{
   
private bool _isCalendarVisible;

   
public CalendarVisibilityChangedEventArgs(bool isCalendarVisible)
    {
       
this._isCalendarVisible = isCalendarVisible;
    }

   
public bool IsCalendarVisible
    {
       
get
        {
           
return this._isCalendarVisible;
        }
    }
}

public delegate void CalendarVisibilityChangedEventHandler(object sender, CalendarVisibilityChangedEventArgs e);

public delegate void DateSelectedEventHandler(object sender, DateSelectedEventArgs e);

To consume the event, create an event handler method as shown below.
protected void CalendarUserControl1_DateSelected(object sender, DateSelectedEventArgs e)
{
    Response.Write(
"Selected Date = " + e.SelectedDate.ToShortDateString());
}

Register event handler method "CalendarUserControl1_DateSelected()" with "DateSelected" event of the "CalendarUserControl" using "+=" as shown below. Do this, in the Page_load() event of "WebForm1". To unregister we can use "-=".
protected void Page_Load(object sender, EventArgs e)
{
CalendarUserControl1.DateSelected +=
    new DateSelectedEventHandler(CalendarUserControl1_DateSelected);
}

Here is the complete code for WebForm1.aspx.cs, that consumes both the custom events.
public partial class WebForm1 : System.Web.UI.Page
{
   
protected void Page_Load(object sender, EventArgs e)
    {
        CalendarUserControl1.CalendarVisibilityChanged +=
           
new CalendarVisibilityChangedEventHandler(CalendarUserControl1_CalendarVisibilityChanged);

        CalendarUserControl1.DateSelected +=
           
new DateSelectedEventHandler(CalendarUserControl1_DateSelected);
    }

   
protected void CalendarUserControl1_CalendarVisibilityChanged(object sender, CalendarVisibilityChangedEventArgs e)
    {
        Response.Write(
"Calendar Visible = " + e.IsCalendarVisible.ToString());
    }

   
protected void CalendarUserControl1_DateSelected(object sender, DateSelectedEventArgs e)
    {
        Response.Write(
"Selected Date = " + e.SelectedDate.ToShortDateString());
    }

   
protected void Button1_Click(object sender, EventArgs e)
    {
        Response.Write(CalendarUserControl1.SelectedDate);
    }
}

Hopefully, by now we should have a good understanding of events & delegates, and raising and consuming custom events. If there are any questions or feedback, please feel free to leave a comment.

Loading user controls dynamically - Part 109

Suggested Videos
Part 106 - Raising custom events from user controls
Part 107 - Consuming user control custom events
Part 108 - Events and delegates in c#

In this video we will discuss about loading user controls dynamically. Normally, we drag and drop user controls on the webform, at design time. However, there could be several reasons in real time, for loading user controls dynamically. For example, depending on logged in user preferences like age, gender, location etc, we may want to load different user controls. Along the same line, based on Admin and Non-Admin users, different user controls should be loaded.



In most of the internet articles, I read that, if we want, the dynamically created controls, to maintain viewstate across postback, the controls should be loaded in Page_Init() event of the webform. However, I used the Page_Load() event, but the controls are still able to retain their state across postback.

Let us add the CalendarUserControl to the webform. Drag and drop, PlaceHolder control, where we want the controls to be on the page. If we don't use the PlaceHolderControl, and if we try to add controls using the following code, we may get a runtime HttpException.
Control 'CU1_txtDate' of type 'TextBox' must be placed inside a form tag with runat=server
this.Page.Controls.Add(LoadControl("~/UserControls/CalendarUserControl.ascx"));



WebForm1.aspx HTML
<form id="form1" runat="server">
<div>
    
<asp:PlaceHolder ID="PlaceHolder1" runat="server">
   
</asp:PlaceHolder>
    
<br />
    
<asp:Button ID="Button1" runat="server" Text="Button" 
   
onclick="Button1_Click" />
</div>
</form>

Webform1.aspx.cs Code
protected void Page_Load(object sender, EventArgs e)
{
   
CalendarUserControl calendarUserControl =
        (
CalendarUserControl)LoadControl("~/UserControls/CalendarUserControl.ascx");
    calendarUserControl.ID =
"CU1";
    calendarUserControl.DateSelected +=
       
new DateSelectedEventHandler(calendarUserControl_DateSelected);
    calendarUserControl.CalendarVisibilityChanged +=
       
new CalendarVisibilityChangedEventHandler(calendarUserControl_CalendarVisibilityChanged);
    PlaceHolder1.Controls.Add(calendarUserControl);
}

protected void calendarUserControl_CalendarVisibilityChanged(object sender, CalendarVisibilityChangedEventArgs e)
{
    Response.Write(
"Calende Visible = " + e.IsCalendarVisible.ToString());
}

protected void calendarUserControl_DateSelected(object sender, DateSelectedEventArgs e)
{
    Response.Write(e.SelectedDate.ToShortDateString());
}

protected void Button1_Click(object sender, EventArgs e)
{
    Response.Write(((CalendarUserControl)PlaceHolder1.FindControl(
"CU1")).SelectedDate);
}

Loading controls dynamically in ASP.NET - Part 110

Suggested Videos
Part 107 - Consuming user control custom events
Part 108 - Events and delegates in c#
Part 109 - Loading user controls dynamically

In this video we will discuss about
1. Adding controls dynamically
2. Tips and tricks to maintain the state of dynamically added controls across postback



To maintain the state of controls across postback
1. Add the controls in the page load event, and set their visibility to false.
2. Based on the DropDownList selection, show/hide the dynamically added controls

ASPX Page HTML
<div>
    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True">
        <asp:ListItem Text="Please Select" Value="-1"></asp:ListItem>
        <asp:ListItem Text="Select City" Value="DDL"></asp:ListItem>
        <asp:ListItem Text="Enter Post Code" Value="TB"></asp:ListItem>
    </asp:DropDownList>
    <br />
    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
    <br />
    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</div>



Code Behind Code
protected void Page_Load(object sender, EventArgs e)
{
   
TextBox TB = new TextBox();
    TB.ID =
"TB1";
    PlaceHolder1.Controls.Add(TB);
    TB.Visible =
false;

   
DropDownList DDL = new DropDownList();
    DDL.ID =
"DDL1";
    DDL.Items.Add(
"New York");
    DDL.Items.Add(
"New Jersey");
    DDL.Items.Add(
"Washington DC");
    PlaceHolder1.Controls.Add(DDL);
    DDL.Visible =
false;

   
if (DropDownList1.SelectedValue == "TB")
    {
        TB.Visible =
true;
    }
   
else if (DropDownList1.SelectedValue == "DDL")
    {
        DDL.Visible =
true;
    }
}

protected void Button1_Click(object sender, EventArgs e)
{
   
if (DropDownList1.SelectedValue == "TB")
    {
        Response.Write(((
TextBox)PlaceHolder1.FindControl("TB1")).Text);
    }
   
else if (DropDownList1.SelectedValue == "DDL")
    {
        Response.Write(((
DropDownList)PlaceHolder1.FindControl("DDL1")).SelectedItem.Text);
    }
}

Navigating to a specific month and an year in an asp.net calendar control - Part 111

Suggested Videos
Part 108 - Events and delegates in c#
Part 109 - Loading user controls dynamically
Part 110 - Loading asp.net controls dynamically



This question was asked by 3 to 4 youtube subscribers of my channel. There are several reasons or situations in real time, where we need to navigate to a specific month and an year in an asp.net calendar control. For example, if the date of birth of a person is in the year 1960, we may have to click on the calendar control several times to navigate to that year.

Let's see, how to skip months and years, so that the dates that are too far in the past or future can be easily selected. To achieve this



Step 1: Create an XML file with name Years.XML. Copy and paste the following XML.
<?xml version="1.0" encoding="utf-8" ?>
<Years>
  <Year>
    <Number>2000</Number>
    <Value>2000</Value>
  </Year>
  <Year>
    <Number>2001</Number>
    <Value>2001</Value>
  </Year>
  <Year>
    <Number>2002</Number>
    <Value>2002</Value>
  </Year>
  <Year>
    <Number>2003</Number>
    <Value>2003</Value>
  </Year>
  <Year>
    <Number>2004</Number>
    <Value>2004</Value>
  </Year>
  <Year>
    <Number>2005</Number>
    <Value>2005</Value>
  </Year>
  <Year>
    <Number>2006</Number>
    <Value>2006</Value>
  </Year>
  <Year>
    <Number>2007</Number>
    <Value>2007</Value>
  </Year>
  <Year>
    <Number>2008</Number>
    <Value>2008</Value>
  </Year>
  <Year>
    <Number>2009</Number>
    <Value>2009</Value>
  </Year>
  <Year>
    <Number>2010</Number>
    <Value>2010</Value>
  </Year>
  <Year>
    <Number>2011</Number>
    <Value>2011</Value>
  </Year>
  <Year>
    <Number>2012</Number>
    <Value>2012</Value>
  </Year>
  <Year>
    <Number>2013</Number>
    <Value>2013</Value>
  </Year>
</Years>

Step 2: Create an XML file with name Months.XML. Copy and paste the following XML.
<?xml version="1.0" encoding="utf-8" ?>
<Months>
  <Month>
    <Number>1</Number>
    <Name>January</Name>
  </Month>
  <Month>
    <Number>2</Number>
    <Name>February</Name>
  </Month>
  <Month>
    <Number>3</Number>
    <Name>March</Name>
  </Month>
  <Month>
    <Number>4</Number>
    <Name>April</Name>
  </Month>
  <Month>
    <Number>5</Number>
    <Name>May</Name>
  </Month>
  <Month>
    <Number>6</Number>
    <Name>June</Name>
  </Month>
  <Month>
    <Number>7</Number>
    <Name>July</Name>
  </Month>
  <Month>
    <Number>8</Number>
    <Name>August</Name>
  </Month>
  <Month>
    <Number>9</Number>
    <Name>September</Name>
  </Month>
  <Month>
    <Number>10</Number>
    <Name>October</Name>
  </Month>
  <Month>
    <Number>11</Number>
    <Name>November</Name>
  </Month>
  <Month>
    <Number>12</Number>
    <Name>December</Name>
  </Month>
</Months>

Step 3: Copy and paste the following HTML in any webform
<div style="font-family:Arial">
    Year :
    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True"
        onselectedindexchanged="DropDownList1_SelectedIndexChanged">
    </asp:DropDownList>&nbsp;
    Month:
    <asp:DropDownList ID="DropDownList2" runat="server" AutoPostBack="True"
        onselectedindexchanged="DropDownList2_SelectedIndexChanged">
    </asp:DropDownList>
    <br />
    <asp:Calendar ID="Calendar1" runat="server"></asp:Calendar>
    <asp:Button ID="Button1" runat="server" onclick="Button1_Click"
        Text="Get Selected Date" />
</div>

Step 4: Copy and paste the following code in the code-behind file
protected void Page_Load(object sender, EventArgs e)
{
   
if (!IsPostBack)
    {
        LoadYears();
        LoadMonths();
    }
}

private void LoadMonths()
{
   
DataSet dsMonths = new DataSet();
    dsMonths.ReadXml(Server.MapPath(
"~/Data/Months.xml"));

    DropDownList2.DataTextField =
"Name";
    DropDownList2.DataValueField =
"Number";

    DropDownList2.DataSource = dsMonths;
    DropDownList2.DataBind();
}

private void LoadYears()
{
   
DataSet dsYears = new DataSet();
    dsYears.ReadXml(Server.MapPath(
"~/Data/Years.xml"));

    DropDownList1.DataTextField =
"Number";
    DropDownList1.DataValueField =
"Number";

    DropDownList1.DataSource = dsYears;
    DropDownList1.DataBind();
}

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
   
int year = Convert.ToInt16(DropDownList1.SelectedValue);
   
int month = Convert.ToInt16(DropDownList2.SelectedValue);
    Calendar1.VisibleDate =
new DateTime(year, month, 1);
    Calendar1.SelectedDate =
new DateTime(year, month, 1);
}

protected void DropDownList2_SelectedIndexChanged(object sender, EventArgs e)
{
   
int year = Convert.ToInt16(DropDownList1.SelectedValue);
   
int month = Convert.ToInt16(DropDownList2.SelectedValue);
    Calendar1.VisibleDate =
new DateTime(year, month, 1);
    Calendar1.SelectedDate =
new DateTime(year, month, 1);
}

protected void Button1_Click(object sender, EventArgs e)
{
    Response.Write(Calendar1.SelectedDate.ToShortDateString());
}

At this point, run the project and you should be able to skip to any month and year in an asp.net calendar control. This code can be encapsulated in an user control, and reused anywhere in the entire project.

Asp.net custom server controls - Part 112

Suggested Videos
Part 109 - Loading user controls dynamically
Part 110 - Loading asp.net controls dynamically
Part 111 - Navigating to a specific month and an year in an asp.net calendar control

In asp.net video series, in parts 104 to 111, we have discussed about asp.net user controls.
Please watch user control videos by clicking here before proceeding with this video.



In this video we will discuss about, asp.net composite custom controls. Unlike UserControls, Composite controls are created completely in code. In the next few videos we will be creating a composite custom calendar control, that is similar to the one in the image below. In parts 104 to 111, we have discussed about achieving the same, by building asp.net CalendarUserControl.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRP4AbrHzGqtQAuXgws7_JGgsMNUAg90KLxK9Tq8y6O6uVxOKTXDju9Dg2_mcEBqpsI1cxKw8OvBqC8uUFoq9Cf0EJuifXKGAxdTFGihLmfdoPBiH0OBtEhBkrbZYn0P1f61IXJhP7x-rm/s1600/asp.net+composite+custom+control.png



The custom calendar control should be capable of doing the following
1. When the user clicks on the calendar image button, the calendar should be visible.
2. Once the user selects a date, from the calendar control, the textbox should be populated with the selected date, and the calendar should become invisible.

1. To get started open visual studio
2. File > New Project
3. In the "New Project" dialog box, select "Web" from "Installed Templates".
4. Select "ASP.NET Server Control"
5. Type "CustomControls" in the "Name" text box
6. Choose C:\ as the location and click "OK"

At this point "CustomControls" project should be created. In the solution explorer rename "ServerControl1.cs" file to "CustomCalendar.cs". Click "Yes" on the message you get.

Copy and paste the following code in CustomCalendar.cs file. The code is well commented, to describe the purpose of various attributes and methods, that we used.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CustomControls
{
   
// Specifies the default tag to generate for our CustomCalendar control 
    // when it is dragged from visual studio toolbox on to the webform 
    [
ToolboxData("<{0}:CustomCalendar runat=server></{0}:CustomCalendar>")]
   
// All composite custom controls inheirt from the base CompositeControl class 
    // that contains all the common functionality needed by all composite controls.
   
public class CustomCalendar : CompositeControl
    {
       
// Child controls required by the CustomCalendar control
       
TextBox textBox;
       
ImageButton imageButton;
       
Calendar calendar;

       
// All child controls are required to be created by overriding 
        // CreateChildControls method inherited from the base Control class
        // CompositeControl inherits from WebControl and WebControl class
        // inherits from Control class
       
protected override void CreateChildControls()
        {
            Controls.Clear();

            textBox =
new TextBox();
            textBox.ID =
"dateTextBox";
            textBox.Width =
Unit.Pixel(80);

            imageButton =
new ImageButton();
            imageButton.ID =
"calendarImageButton";

            calendar =
new Calendar();
            calendar.ID =
"calendarControl";

           
// Add Child controls to CustomCalendar control
           
this.Controls.Add(textBox);
            
this.Controls.Add(imageButton);
            
this.Controls.Add(calendar);
        }

       
// Render the child controls using HtmlTextWriter object
       
protected override void Render(HtmlTextWriter writer)
        {
            textBox.RenderControl(writer);
            imageButton.RenderControl(writer);
            calendar.RenderControl(writer);
        }
    }
}

At this point we are done, building the composite custom control. However, there will be several problems with this control. In the upcoming videos, we will discuss about solving the problems one by one. In our next video session, we will discuss about using this composite custom control in an asp.net web application.

 

Adding composite custom controls to visual studio tool box - Part 113

Suggested Videos
Part 110 - Loading asp.net controls dynamically
Part 111 - Navigating to a specific month and an year in an asp.net calendar control
Part 112 - ASP.NET custom server controls

In this video we will discuss about
1. Adding composite custom controls to visual studio toolbox
2. Using composite custom controls in an asp.net web application



In Part 112, we discussed about building composite custom controls. Please watch Part 112, before proceeding with this video.

Adding composite custom controls to visual studio toolbox:
1. Build the "CustomControls" project that we have developed in
Part 112 of asp.net video series. Building the project should produce "CustomControls.dll" assembly which contains our "CustomCalendar" control. Since, we have created the project in C:\ drive, the assembly should be present at the following path.
C:\CustomControls\CustomControls\bin\Debug
2. Open visual studio. Create a new asp.net web application project.
3. In visual studio toolbox, right click anywhere, and select "Add Tab"
4. Name the tab "Custom Controls".
5. Right click under "Custom Controls" and select "Choose Items"
6. In the "Choose Toolbox Items" dialog box, click "Browse" button.
7. Navigate to "C:\CustomControls\CustomControls\bin\Debug" and select "CustomControls.dll" and click "Open"
8. Now click "OK" on the "Choose Toolbox Items" dialog box.
9. Notice that "CustomCalendar" control is added to the toolbox under "Custom Controls" tab.



Using composite custom controls in an asp.net web application:
Flip "WebForm1.aspx" to "Design" mode. Drag and Drop "CustomCalendar" control onto "WebForm1.aspx". This should automatically add the control to the webform and the control declaration looks as as shown below, in the source mode of webform1.aspx.
<cc1:CustomCalendar ID="CustomCalendar1" runat="server" />

Notice that a "Register" directive is also automatically, added under "Page" directive.
<%@ Register assembly="CustomControls" namespace="CustomControls" tagprefix="cc1" %>

At this point, run the project and notice that the "CustomCalendar" control has several issues. For example
1. There is no image associated with the Image button
2. The calendar is always visible. We want the Calendar to be invisible at first. The calendar should be shown, when the user clicks the image button.
3. Also, when select a date with in calendar, nothing happens. We want the text box, to be populated with the selected date.

 


Adding properties to composite custom controls - Part 114

Suggested Videos
Part 111 - Navigating to a specific month and an year in an asp.net calendar control
Part 112 - ASP.NET custom server controls
Part 113 - Adding composite custom controls to visual studio tool box

In this video we will discuss about adding custom properties, to composite custom calendar control. Please watch
Part 113 of asp.net video series before proceeding with this video.



At the moment, the calendar composite control does not have an image associated with the image button. Let us create "ImageButtonImageUrl" property to associate an image.

Copy and paste the following code in CustomCalendar.cs file.
[
Category("Appearance")]
[
Description("Sets the image icon for the calendar control")]
public string ImageButtonImageUrl
{
   
get
    {
       
// This method checks if the child controls are created, if not, 
        // it triggers a call to CreateChildControls() method.
        EnsureChildControls();
       
return imageButton.ImageUrl != null ? imageButton.ImageUrl : string.Empty;
    }
   
set
    {
        EnsureChildControls();
        imageButton.ImageUrl =
value;
    }
}



Rebuild CustomControls project.

Flip to the asp.net web application project, where the CustomCalendar is being tested. Please remove the CustomCalendar control from visual  studio tool boox, and add it again. Drag and drop CustomCalendar control on to the webform. Right click and select properties. Notice that "ImageButtonImageUrl" property is now displayed in the properties window. If you change the properties display mode to "Categorized", then notice that "ImageButtonImageUrl" property is displayed under "Appearance" category. Also, notice that, when the property is selected, the property description is displayed at the bottom of the properties window.

Create a folder with Name=Images in the asp.net web application project. Download Calendar.jpg image from this website. To download the image, simply right click on the image, and select "Save Image as" and save it to the specified location on your computer. Copy the image into the "Images" folder in your asp.net web application project.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2Mz1da5Tfc9NwOBTcau_OEFIoVWpG3AfhfAxiJBT_7LCxLFdlwldP7Phto-jWcBCwDCe7nMiXMJ3fA0ycKuUQhMfmJZZoqM1S3N6uw50xf2ONXvT-tJk1C1GuelldvgYRVdA0LxdaVaaR/s1600/Calendar.jpg

Now, in the properties window, set ImageButtonImageUrl="Images/Calendar.jpg". Notice that, at design time, the image is not shown on the image button. Run the project, and notice that, at run time, the image button shows the image as expected.

To correct the design time problem, override RecreateChildControls() method. This method is called by visual studio designer, to recreate child controls at design time. Copy and paste the following code CustomCalendar.cs file.
protected override void RecreateChildControls()
{
    EnsureChildControls();
}

At this point, re-test the custom calendar. When you set ImageButtonImageUrl="Images/Calendar.jpg", notice that the property change is immediately picked up by the control at design time.

At the moment, another cosmetic issue with this control is that, the "Image Button" and the "TextBox" are not properly alligned. To correct this problem, change the Render() method in CustomCalendar.cs file, as shown below. This method adds, cellpadding attribute, and puts the "textbox" and "calendar" in a table.
protected override void Render(HtmlTextWriter writer)
{
    AddAttributesToRender(writer);
    writer.AddAttribute(
HtmlTextWriterAttribute.Cellpadding, "1");

    writer.RenderBeginTag(
HtmlTextWriterTag.Table);

    writer.RenderBeginTag(
HtmlTextWriterTag.Tr);

    writer.RenderBeginTag(
HtmlTextWriterTag.Td);
    textBox.RenderControl(writer);
    writer.RenderEndTag();

    writer.RenderBeginTag(
HtmlTextWriterTag.Td);
    imageButton.RenderControl(writer);
    writer.RenderEndTag();

    writer.RenderEndTag();
    writer.RenderEndTag();

    calendar.RenderControl(writer);
}

Here is the complete code for CustomCalendar:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CustomControls
{
    [
ToolboxData("<{0}:CustomCalendar runat=server></{0}:CustomCalendar>")]
   
public class CustomCalendar : CompositeControl
    {
       
TextBox textBox;
       
ImageButton imageButton;
       
Calendar calendar;

        [
Category("Appearance")]
        [
Description("Sets the image icon for the calendar control")]
       
public string ImageButtonImageUrl
        {
           
get
            {
                EnsureChildControls();
               
return imageButton.ImageUrl != null ? imageButton.ImageUrl : string.Empty;
            }
           
set
            {
                EnsureChildControls();
                imageButton.ImageUrl =
value;
            }
        }

       
protected override void RecreateChildControls()
        {
            EnsureChildControls();
        }

       
protected override void CreateChildControls()
        {
            Controls.Clear();

            textBox =
new TextBox();
            textBox.ID =
"dateTextBox";
            textBox.Width =
Unit.Pixel(80);

            imageButton =
new ImageButton();
            imageButton.ID =
"calendarImageButton";

            calendar =
new Calendar();
            calendar.ID =
"calendarControl";

           
this.Controls.Add(textBox);
            
this.Controls.Add(imageButton);
            
this.Controls.Add(calendar);
        }

       
protected override void Render(HtmlTextWriter writer)
        {
            AddAttributesToRender(writer);
            writer.AddAttribute(
HtmlTextWriterAttribute.Cellpadding, "1");

            writer.RenderBeginTag(
HtmlTextWriterTag.Table);

            writer.RenderBeginTag(
HtmlTextWriterTag.Tr);

            writer.RenderBeginTag(
HtmlTextWriterTag.Td);
            textBox.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(
HtmlTextWriterTag.Td);
            imageButton.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderEndTag();
            writer.RenderEndTag();

            calendar.RenderControl(writer);
        }
    }
}

Solving the problems of asp.net composite custom calendar control - Part 115
Suggested Videos
Part 112 - ASP.NET custom server controls
Part 113 - Adding composite custom controls to visual studio tool box
Part 114 - Adding properties to composite custom controls

In Parts 112 to 114  in asp.net video series, we discussed about the basics of composite custom controls in asp.net. Please watch Parts 112 to 114, before proceeding with this video.
Click here to access asp.net video tutorial



In this video we will discuss about
1. Hiding the calendar control, when the CustomCalendar control is first loaded
2. Displaying and hiding the calendar, when the image button is clicked
3. Populating the textbox control, with a date that is selected from the calendar
4. Retrieving the selected date from the CustomCalendar control on a webform.



Hiding the calendar control, when the CustomCalendar control is first loaded:
To hide the calendar set calendar.Visible =
false in CreateChildControls() method in CustomCalendar.cs file

Displaying and hiding the calendar, when the image button is clicked:
To toggle the visibility of the calendar object, first register an event handler method, with the click event of the image button in CreateChildControls() method as shown below.
imageButton.Click +=
new ImageClickEventHandler(imageButton_Click);

Provide the implementation for imageButton_Click() event handler method as shown below:
void imageButton_Click(object sender, ImageClickEventArgs e)
{
    // If the calendar is visible, make it invisible
   
if (calendar.Visible)
    {
        calendar.Visible =
false;
    }
    // If the calendar is invisible, make it visible
   
else
    {
        calendar.Visible =
true;
       
// if the user has not already selected a date, then set
        // set the VisibleDate of the calendar to today's date
       
if (string.IsNullOrEmpty(textBox.Text))
        {
            calendar.VisibleDate =
DateTime.Today;
        }
       
// if the user has already selected a date, then set
        // set the VisibleDate of the calendar to the selected date
        // by retrieving it from the textbox
       
else
        {
           
DateTime output = DateTime.Today;
           
bool isDateTimeConverionSuccessful = DateTime.TryParse(textBox.Text, out output);
            calendar.VisibleDate = output;
        }
    }
}

Populating the textbox control, with a date that is selected from the calendar:
First register an event handler method, with the "SelectionChanged" event of the calendar in CreateChildControls() method as shown below.
calendar.SelectionChanged +=
new EventHandler(calendar_SelectionChanged);

Provde the implementation for calendar_SelectionChanged() event handler method as shown below.
void calendar_SelectionChanged(object sender, EventArgs e)
{
   
// Populate the text box wit the selected date
    textBox.Text = calendar.SelectedDate.ToShortDateString();
    // Make the calendar invisible
    calendar.Visible =
false;
}

Retrieving the selected date from the CustomCalendar control on a webform:
To retrieve the selected date from the CustomCalendar control, add SelectedDate property to the CustomCalendar class as shown below.
[
Category("Appearance")]
[
Description("Gets or sets the selected date of custom calendar control")]
public
DateTime SelectedDate
{
   
get
    {
        EnsureChildControls();
       
return string.IsNullOrEmpty(textBox.Text) ? DateTime.MinValue : Convert.ToDateTime(textBox.Text);
    }

   
set
    {
       
if (value != null)
        {
            EnsureChildControls();
            textBox.Text = value.ToShortDateString();
        }
       
else
        {
            EnsureChildControls();
            textBox.Text = "";
        }
    }
}

Here is the complete code for CustomCalendar control so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CustomControls
{
   
    [
ToolboxData("<{0}:CustomCalendar runat=server></{0}:CustomCalendar>")]
   
public class CustomCalendar : CompositeControl
    {
       
TextBox textBox;
       
ImageButton imageButton;
       
Calendar calendar;

       
protected override void CreateChildControls()
        {
            Controls.Clear();

            textBox =
new TextBox();
            textBox.ID =
"dateTextBox";
            textBox.Width =
Unit.Pixel(80);

            imageButton =
new ImageButton();
            imageButton.ID =
"calendarImageButton";
            imageButton.Click +=
new ImageClickEventHandler(imageButton_Click);

            calendar =
new Calendar();
            calendar.ID =
"calendarControl";
            calendar.SelectionChanged +=
new EventHandler(calendar_SelectionChanged);
            calendar.Visible =
false;

           
this.Controls.Add(textBox);
            
this.Controls.Add(imageButton);
            
this.Controls.Add(calendar);
        }

       
void calendar_SelectionChanged(object sender, EventArgs e)
        {
            textBox.Text = calendar.SelectedDate.ToShortDateString();
            calendar.Visible =
false;
        }

       
void imageButton_Click(object sender, ImageClickEventArgs e)
        {
           
if (calendar.Visible)
            {
                calendar.Visible =
false;
            }
           
else
            {
                calendar.Visible =
true;
               
if (string.IsNullOrEmpty(textBox.Text))
                {
                    calendar.VisibleDate =
DateTime.Today;
                }
                else
                {
                   
DateTime output = DateTime.Today;
                   
bool isDateTimeConverionSuccessful = DateTime.TryParse(textBox.Text, out output);
                    calendar.VisibleDate = output;
                }
            }
        }

        [
Category("Appearance")]
        [
Description("Sets the image icon for the calendar control")]
       
public string ImageButtonImageUrl
        {
           
get
            {
                EnsureChildControls();
               
return imageButton.ImageUrl != null ? imageButton.ImageUrl : string.Empty;
            }
           
set
            {
                EnsureChildControls();
                imageButton.ImageUrl =
value;
            }
        }

        [
Category("Appearance")]
        [
Description("Gets or sets the selected date of custom calendar control")]
       
public DateTime SelectedDate
        {
           
get
            {
                EnsureChildControls();
               
return string.IsNullOrEmpty(textBox.Text) ? DateTime.MinValue : Convert.ToDateTime(textBox.Text);
            }

           
set
            {
               
if (value != null)
                {
                    EnsureChildControls();
                    textBox.Text = value.ToShortDateString();
                }
               
else
                {
                    EnsureChildControls();
                    textBox.Text = "";
                }
            }
        }

       
protected override void RecreateChildControls()
        {
            EnsureChildControls();
        }

       
protected override void Render(HtmlTextWriter writer)
        {
            AddAttributesToRender(writer);
            writer.AddAttribute(
HtmlTextWriterAttribute.Cellpadding, "1");

            writer.RenderBeginTag(
HtmlTextWriterTag.Table);

            writer.RenderBeginTag(
HtmlTextWriterTag.Tr);

            writer.RenderBeginTag(
HtmlTextWriterTag.Td);
            textBox.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(
HtmlTextWriterTag.Td);
            imageButton.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderEndTag();
            writer.RenderEndTag();

            calendar.RenderControl(writer);
        }
    }
}

Please build CustomControls project, and add a reference to CustomCalendar in asp.net web application for testing. Drag and drop the CustomCalendar control and a button onto the webform.

Double click the button control to generate the click event handler.
protected void Button1_Click(object sender, EventArgs e)
{
    Response.Write(CustomCalendar1.SelectedDate.ToShortDateString());
}

Run the web application and select a date from the calendar control. Notice that the textbox is populated with the selected date. Now click the button. The selected date should be printed on the web form.

No comments:

Post a Comment