Sunday, 9 December 2012

Data View & Data Source Controls in Asp Net

Goals:
  • Present data source and data view controls.
Prerequisites:
  • The Northwind database installed in SQL Server instance. [Northwind's script]
Steps:
  1. Create a new ASP.NET Web Application project in Visual Studio.
  2. There are two types of server controls participate in the declarative data binding model:
    • Data source controls:
      • They do not render any user interface.
      • They act as an intermediary between a particular data store and other controls on the ASP.NET Web page.
      • They enable rich capabilities for retrieving and modifying data, including querying, sorting, paging, filtering, updating, deleting, and inserting.
      • Depending of the source of the data, one of the following controls can be used:
        • SqlDataSource - for any SQL database; it returns data as DataReader or DataSet objects
        • AccessDataSource - specialized version of the SqlDataSource control - only for Microsoft Access
        • LinqDataSource - for LINQ to SQL
        • EntityDataSource (3.5 SP1) - for Entity Framework
        • XmlDataSource - for data stored in XML files
        • SiteMapDataSource - special data source for a definition of web site's structure; used by navigational controls
        • ObjectDataSource - for special, custom logic of loading data (e.g. from services)
    • Data bound (data view) controls:
      • Controls designed to display bound data:
        • DetailsView
        • FormView
        • DataList
        • ListView
        • DataPager (it does not display the data, but allows to add paging for e.g. a ListView control)
      • Other controls that can be used to display bound data:
        • GridView
        • Repeater
  3. SqlDataSource
    • Add a SqlDataSource to the page.
    • Choose the 'Configure Data Source' task (available at the small button attached to the control in the Design mode). Choose the Northwind database and than the Customers table. We will allow the user to modify the displayed data, so using the Advanced button set the option of generating insert, update, and delete commands also:
    • The following markup code is generated:
      <asp:SqlDataSource ID="SqlDataSource1" runat="server"
          
      ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
          
      DeleteCommand="DELETE FROM [Customers] WHERE [CustomerID] = @CustomerID"
          
      InsertCommand="INSERT INTO [Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax]) VALUES (@CustomerID, @CompanyName, @ContactName, @ContactTitle, @Address, @City, @Region, @PostalCode, @Country, @Phone, @Fax)"
          
      SelectCommand="SELECT * FROM [Customers]"
          
      UpdateCommand="UPDATE [Customers] SET [CompanyName] = @CompanyName, [ContactName] = @ContactName, [ContactTitle] = @ContactTitle, [Address] = @Address, [City] = @City, [Region] = @Region, [PostalCode] = @PostalCode, [Country] = @Country, [Phone] = @Phone, [Fax] = @Fax WHERE [CustomerID] = @CustomerID">    <DeleteParameters>
              <asp:Parameter Name="CustomerID" Type="String" />     </DeleteParameters>
          <UpdateParameters>
              <asp:Parameter Name="CompanyName" Type="String" />         <asp:Parameter Name="ContactName" Type="String" />         <asp:Parameter Name="ContactTitle" Type="String" />         <asp:Parameter Name="Address" Type="String" />         <asp:Parameter Name="City" Type="String" />         <asp:Parameter Name="Region" Type="String" />         <asp:Parameter Name="PostalCode" Type="String" />         <asp:Parameter Name="Country" Type="String" />         <asp:Parameter Name="Phone" Type="String" />         <asp:Parameter Name="Fax" Type="String" />         <asp:Parameter Name="CustomerID" Type="String" />     </UpdateParameters>
          <InsertParameters>
              <asp:Parameter Name="CustomerID" Type="String" />         <asp:Parameter Name="CompanyName" Type="String" />         <asp:Parameter Name="ContactName" Type="String" />         <asp:Parameter Name="ContactTitle" Type="String" />         <asp:Parameter Name="Address" Type="String" />         <asp:Parameter Name="City" Type="String" />         <asp:Parameter Name="Region" Type="String" />         <asp:Parameter Name="PostalCode" Type="String" />         <asp:Parameter Name="Country" Type="String" />         <asp:Parameter Name="Phone" Type="String" />         <asp:Parameter Name="Fax" Type="String" />     </InsertParameters>
      </
      asp:SqlDataSource>
      Note that using the SqlDataSource control allows to create a web database application in seconds, but the generated code is quite hard to maintain - there are no data access and data logic layers, everything is mixed in the presentation layer.
  4. GridView
    • Add a GridView control to the page. As the DataSourceID, set the SqlDataSource1 control. Note that columns are automatically generated. Select also all checkboxes on the GridView Tasks window to enable additional options:
    • Run the page and note how easy was to create quite functional grid for presenting data for modification:
    • After a few more seconds and clicks (auto format, font, alignment of the pager), the page can change its appearance radically:
  5. LinqDataSource
    • Add a new 'LINQ to SQL Classes' item to the project:
    • Add all tables of the Northwind database to the new created DataClasses1.dbml file (drag them from the Server Explorer window):
    • Add a new page (i.e. a Web Form item) to the project.
    • Add a new LinqDataSource control to the page. Configure it using the 'Configure Data Source' task:

      (If the list of available context objects is empty, compile the project and try again.)
    • As in the previous example, we will allow the user to modify data:
    • We have chosen the Customers table, so name the control customersLinqDataSource.
    • Add another LinqDataSource named ordersLinqDataSource attached to the Orders table:
  6. DetailsView
    • Add a DetailsView control to the page. Set its DataSourceID to customersLinqDataSource and enable some additional features:
    • Run the page and check its functionality:
    • Let's display all orders of the selected customer at the right side using a grid:
      • Create a Table with 2 cells, put the DetailsView control to the left cell and the GridView control to the right one:
      • Set the ordersLinqDataSource control for the DataSourceID property of the GridView.
      • Run the page and note that data in the GridView is not filtered for the customer selected in the DetailsView control:
      • There is no need to write code to set the proper filter for the grid, it is enough to configure the ordersLinqDataSource control using the Visual Designer:
      • Make some cosmetic changes in the appearance of both visible controls and enjoy the result:
  7. FormView
    • The next step to improve our web application is to create a page that displays details of an order in a nice and easy to modify way.
    • Add a new page to the project, name it order.aspx.
    • Add a LinqDataSource control:
      • Name it orderLinqDataSource.
      • Configure it to get data from the Orders table of the DataClasses1 source. Be sure to enable modifying the data:
      • We want to display a single order, so we should filter the data source. As a filtering parameter we use OrderID which will be passed to the page in the query string:

        Be sure to set the default value for the parameter taken from the QueryString. Without this default value, the LinqDataSource control would try force converting nothing to an integer value and as a result the user would see an exception displayed on the page.
    • Add a FormView control to the page, set the DataSourceID property to orderLinqDataSource:
    • In most of data view controls, it is possible to define what should be displayed if there is no data. For the FormView control, it can be done by defining the EmptyDataTemplate:
    • Run the page:
    • If there is a proper OrderID parameter in the query string, the page displays data of the order:
    • To allow the user to jump directly to the order's details from the list of orders, set the Enable Selection options of the GridView control presenting orders to true:

      and add a handler for the SelectedIndexChanged event of the grid:
      protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
      {
          Server.Transfer(
      "~/order.aspx?OrderID=" + (int)GridView1.SelectedValue);
      }
      Note that transferring a request using the Server.Transfer method has some disadvantages. The better way would be adding a special column to the GridView control with manually created hyperlinks.
  8. ObjectDataSource
    • The last taks of this tutorial is to create a page displaying short information about customers in a form of a pageable list. Displayed information should contain: CustomerID, CompanyName, and number of orders.
    • Add to the project a class that will serve data (it will be used by the ObjectDataSource):
      using System;using System.Linq;using System.Data.Linq;using System.Collections;
      namespace DataControls
      {
          
      public class CustomersShortInfo     {
              
      private static DataClasses1DataContext customersDC;
              
      protected static DataClasses1DataContext CustomersDC
              {
                  
      get
                  {
                      
      if (customersDC == null)
                      {
                          customersDC =
      new DataClasses1DataContext();
                      }
                      
      return customersDC;
                  }
              }

              
      public static int GetCount()
              {
                  
      return CustomersDC.Customers.Count();
              }

              
      public static IEnumerable GetData(int startRowIndex, int maximumRows)
              {
                  
      var data =
                      (
      from c in CustomersDC.Customers
                      
      select new                  {
                           c.CustomerID,
                           c.CompanyName,
                           NumberOrders = c.Orders.Count
                       }
                      ).Skip(startRowIndex).Take(maximumRows);
                  
      return data;
              }
          }
      }
    • Add an ObjectDataSource control to the page. Configure it to use the GetData method of the CustomersShortInfo class to get data:
    • Modify the generated markup code to get such code:
      <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
          
      TypeName="DataControls.CustomersShortInfo"
          
      EnablePaging="True"
          
      SelectMethod="GetData" SelectCountMethod="GetCount">
      </
      asp:ObjectDataSource>
      (Parameters of the GetData method are used automatically when paging is enabled, explicit declaration would cause problems.)
  9. ListView
    • Add a ListView control to the page.

      If there is no such control on the Toolbox, do not worry, just start typing '<asp:ListView' in the Source view of the page.
    • To make it work, the LayoutTemplate and ItemTemplate of the ListView control must be set. Additionally, because we expect paging parameters in the GetData method, a DataPager control must be used:
      <asp:ListView ID="ListView1" runat="server" DataSourceID="ObjectDataSource1">
          <LayoutTemplate>
              <div runat="server" id="lstProducts">
                  <div runat="server" id="itemPlaceholder" />         </div>
              <asp:DataPager ID="DataPager1" runat="server" PageSize="5">
                  <Fields>
                      <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />             </Fields>
              </asp:DataPager>
          </LayoutTemplate>
          <ItemTemplate>
              <div >             ID: <asp:Label ID="Label1" runat="server" Text='<%# Eval("CustomerID")%>' /><br />             Company name: <asp:Label ID="Label2" runat="server" Text='<%# Eval("CompanyName")%>' /><br />             Number of orders: <asp:Label ID="Label3" runat="server" Text='<%# Eval("NumberOrders")%>' />         </div>
              <br />     </ItemTemplate>
      </
      asp:ListView>
    • Run the page:
    • The appearance of data can be almost freely modified, e.g.:

       
      <asp:ListView ID="ListView2" runat="server" DataSourceID="ObjectDataSource1">
          <LayoutTemplate>
              <asp:DataPager ID="DataPager1" runat="server" PageSize="20">
                  <Fields>
                      <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />             </Fields>
              </asp:DataPager>
              <br />         <div runat="server" id="lstProducts">
                  <span runat="server" id="itemPlaceholder"/>
              </div>
          </LayoutTemplate>
          <ItemTemplate>
              <div style="float: left; width: 200px; margin: 20px 20px 20px 20px;">
                  ID: <asp:Label ID="Label1" runat="server" Text='<%# Eval("CustomerID")%>' /><br />             Company name: <asp:Label ID="Label2" runat="server" Text='<%# Eval("CompanyName")%>' /><br />             Number of orders: <asp:Label ID="Label3" runat="server" Text='<%# Eval("NumberOrders")%>' />         </div>
          </ItemTemplate>
      </
      asp:ListView>
[Source code]

Validation ASP.NET Server Controls

Goals:
  • Present ASP.NET validation controls.
Steps:
  1. Create a new ASP.NET Web Application project in Visual Studio.
  2. Add a Button and a Literal to the page:
    <asp:Button ID="PostbackButton" runat="server" onclick="PostbackButton_Click"
        
    Text="PostbackButton" />
    <
    asp:Literal ID="statusLiteral" runat="server"></asp:Literal>
    Add also code for the PostbackButton_Click method:
    protected void PostbackButton_Click(object sender, EventArgs e)
    {
        statusLiteral.Text =
    "PostbackButton_Click called";
    }
  3. RequiredFieldValidator
    • Add a TextBox control. Add also a RequiredFieldValidator control (from the Validation group in the Toolbox window) attached to this TextBox (using the ControlToValidate property):

      Run the page and note that the validator is hidden initially. It is visible only in case of a try to postback the page with empty value in the TextBox.
      Note also that the red error information displayed by the validator appears immediately. It is done by the JavaScript code used by the validator internally. All built-in validators have both the JavaScript and C# code for validating values provided by the user on the client and server-side, respectively.
    • The RequiredFieldValidator control works also for other types of controls, e.g. for the DropDownList:

      In this case, the InitialValue property of the RequiredFieldValidator control is the most important - it allows to point the default value which should be treated as non-value.
    • Add 2 additional TextBox controls with RequiredFieldValidator controls, but this time in one line, to see an effect of changing value of the Display property of the validator control.

      Run the page once with Static value for the Display property of the validator and once with Dynamic value. Note the difference in placing controls.
  4. ValidationSummary
    • This control is not a validator but a place for displaying all messages coming from validator controls.
    • It uses the ErrorMessage properties of all validator controls. To see it in action, set the Text properties of all used validators to 'Text of [#]' and ErrorMessage to 'ErrorMessage of [#]':
    • Add the ValidationSummary control under the button:
    • See the ValidationSummary control in action:
    • Make some tests - set or delete value either the ErrorMessage or the Text property. Try also to set the Display property to None.
    • Note also other interesting properties of the ValidationSummary control: DisplayMode, ShowMessageBox, and ShowSummary.
  5. Validators can be grouped by values of the ValidationGroup property. This property can be set for validator controls and all controls that can cause validation, in particular Button controls..
    • Modify the ValidationGroup property to value 'ValGroup1' for all existing validators, the ValidationSummary control, and the button.
    • Run the application and verify that there are no changes.
  6. CompareValidator
    • A classic need for a web application is to ask the user for a password and its confirmation:
      • When values of 2 controls should be compared, the ControlToValidate and ControlToCompare properties must be set.
      • Note that the 2nd button and this CompareValidator have the same value for the ValidationGroup property. Because the name is different than the corresponding value for controls from the first group, this group works independently.
      • Note also that when no password is written, the validator does not work. Use a RequiredFieldValidator control to require the user to enter data in the input control.
    • The CompareValidator control can also be used to check type of a value provided by the user. For example, to force the user to write a proper number:
      • In this case the Type and Operator properties are crucial.
      • Note also usage of the SetFocusOnError property.
    • Not only a type but also a value can be validated:
  7. RangeValidator
    • This control is similar to the CompareValidator control. As an example, ask the user for time:
  8. RegularExpressionValidator
    • This control can be very useful when there is a need to test if the user's input matches a string template. For example, check if the user has written a proper email address:
  9. CustomValidator
    • The CustomValidator control allows to provide a custom validation function in JavaScript and a method in C#. As an example, create a validator that will accept only numbers that can be devided by 5.
    • Add a CustomValidator control, Button, and TextBox. Be sure to set the ValidationGroup property:
    • The logic of the client-side and server-side validation is quite simple. The server-side validation is required to ensure that data provided by the user is correct. The client-side validation is desired to give the user an immediate feedback without waiting for the server's response.
    • The server-side validation must be written as a C# event handler for the ServerValidate event of the CustomValidator:
      protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
      {
          
      int num;
          
      if (int.TryParse(args.Value, out num) && num % 5 == 0)
          {
              args.IsValid =
      true;
          }
          
      else     {
              args.IsValid =
      false;
          }
      }
    • The client-side validation must be a JavaScript function:
      <script language="JavaScript">
          function
      CustomValidator1_ClientValidate(oSrc, args) {
              args.IsValid = (args.Value % 5 == 0);
          }
      </script>
      and the markup for the CustomValidator:
      <asp:CustomValidator ID="CustomValidator1" runat="server"
          
      ControlToValidate="TextBox11" ErrorMessage="Wrong!"
          
      onservervalidate="CustomValidator1_ServerValidate"
          
      ClientValidationFunction="CustomValidator1_ClientValidate"
          ValidationGroup="ValGroup4">
      </
      asp:CustomValidator>
  10. The text displayed by a validator control can use HTML tags. This feature allows to use in example image to notify the user about an error:

    using the following code:
    <asp:CustomValidator ID="CustomValidator1" runat="server"
       
    ControlToValidate="TextBox11" Display="Dynamic"
       
    ErrorMessage="<img src='exclamation.png' />"
       
    onservervalidate="CustomValidator1_ServerValidate"
       
    ClientValidationFunction="CustomValidator1_ClientValidate"
       
    ValidationGroup="ValGroup4">
[Source code]

Advanced ASP NET Server Controls

Goals:
  • Present advanced ASP.NET server controls (data display controls are not included here).
Steps:
  1. Create a new ASP.NET Web Application project in Visual Studio.
  2. Table
    • The Table control is a useful way to dynamically generate or modify a table. The Table's content can be easily created using the Designer:
    • Content of the table can be dynamically modified also:
      protected void Page_Load(object sender, EventArgs e)
      {
          
      if (!IsPostBack)
          {
              Table1.Rows[1].Cells.RemoveAt(2);
              Table1.Rows[1].Cells[0].HorizontalAlign =
      HorizontalAlign.Center;
              Table1.Rows[1].Cells[0].ColumnSpan = 2;

              
      TableRow tr = new TableRow();
              Table1.Rows.Add(tr);

              
      TableCell tc = new TableCell();
              tc.Text =
      "Seventh";
              tr.Cells.Add(tc);

              tc =
      new TableCell();
              tc.Text =
      "Eight";
              tr.Cells.Add(tc);

              tc =
      new TableCell();
              tc.Text =
      "Ninth";
              tr.Cells.Add(tc);
          }
      }
  3. Calendar
    • It is a quite functional control for presenting a calendar to the user.

      Take a look at the generated HTML code to see how many HTML code is necessary to render the calendar.
      Note, that changing a month causes a postback. Unfortunately, this is a limitation of this control. The user's inconvenience can be reduced using AJAX, but for the most demanding users other Calendar control must be used.
    • Selecting a day causes the SelectionChange event:
      protected void Calendar1_SelectionChanged(object sender, EventArgs e)
      {
          Literal7.Text =
      "Selected day: " + Calendar1.SelectedDate.ToString();
      }
  4. AdRotator
    • This is an interesting control which allows to display advertisements to the page.
    • It is based on an XML file containing data of advertisements. Add to the project a new XML file, named Ads.xml, placed in the App_Data folder. Put the following sample content into this file:
      <?xml version="1.0" encoding="utf-8" ?>
      <
      Advertisements>
          <
      Ad>
              <
      ImageUrl>~/Images/1st.jpg</ImageUrl>
              <
      NavigateUrl>http://www.1st.com</NavigateUrl>
              <
      AlternateText>1st</AlternateText>
              <
      Impressions>10</Impressions>
              <
      Keyword></Keyword>
          </
      Ad>
          <
      Ad>
              <
      ImageUrl>~/Images/2nd.jpg</ImageUrl>
              <
      NavigateUrl>http://www.2nd.com</NavigateUrl>
              <
      AlternateText>2nd</AlternateText>
              <
      Impressions>10</Impressions>
              <
      Keyword></Keyword>
          </
      Ad>
          <
      Ad>
              <
      ImageUrl>~/Images/3rd.jpg</ImageUrl>
              <
      NavigateUrl>http://www.3rd.com</NavigateUrl>
              <
      AlternateText>3rd</AlternateText>
              <
      Impressions>10</Impressions>
              <
      Keyword></Keyword>
          </
      Ad>
      </
      Advertisements>
      In this content we assume, that 3 graphics files: 1st.jpg, 2nd.jpg, and 3rd.jpg are located in the Images subfolder.
    • Add the AdRotator control to the page. Click on it '>' small button to open the 'AdRotator Tasks' window, choose an item to create a new Data Source, choose the 'XML File' as a category and point the App_Data/Ads.xml file.

      Note, that a new component of the XmlDataSource type was created automatically.
    • Run the page, refresh it many times in a browser and note that the displayed image changes.
  5. FileUpload
    • The FileUpload control allows in a very easy way to manage a file sent by the user using standard HTML <input type="file"> mechanism.
    • Add the FileUpload control, a Button, and a Literal (the Button is needed to make send action, the Literal is used only for showing some information about the sent file):
    • The sent file must be saved manually, fortunately the FileUpload control has the SaveAs method:
      protected void Button1_Click(object sender, EventArgs e)
      {
          
      if (FileUpload1.HasFile)
          {
              
      try
              {
                  
      string destPath = Server.MapPath("~/App_Data/" + FileUpload1.FileName);
                  FileUpload1.SaveAs(destPath);

                  Literal8.Text =
      string.Format("File name: {0} <br>Size: {1} <br>Content type: {2}",
                      FileUpload1.PostedFile.FileName,
                      FileUpload1.PostedFile.ContentLength,
                      FileUpload1.PostedFile.ContentType);
              }
              
      catch (Exception ex)
              {
                  Literal8.Text =
      "ERROR: " + ex.Message.ToString();
              }
          }
          
      else
          {
              Literal8.Text =
      "No file to send.";
          }
      }
  6. Panel
    • The Panel control provides a container within the page for other controls. It allows to show and hide all contained controls, change their attributes, scroll the content, change the horizontal alignment, and set a background image. See the following example:

      protected void Button2_Click(object sender, EventArgs e)
      {
          Panel1.Visible =
      false;
      }
  7. MultiView, View
    • The MultiView and View server controls work together to enable the capability to turn on/off sections of an ASP.NET page. As an example, add the MultiView control with 3 View controls and add some controls to these Views. Add also a button which will allow to display the next view:
      <asp:MultiView ID="MultiView1" runat="server">
          <asp:View ID="View1" runat="server">
              <asp:Image ID="Image1" runat="server" ImageUrl="Images/1st.jpg" />     </asp:View>
          <asp:View ID="View2" runat="server">
              <asp:Image ID="Image2" runat="server" ImageUrl="Images/2nd.jpg" />     </asp:View>
          <asp:View ID="View3" runat="server">
              <asp:Image ID="Image3" runat="server" ImageUrl="Images/3rd.jpg" />     </asp:View>
      </
      asp:MultiView>
      <
      asp:Button ID="Button3" runat="server" Text="Next view >>"
          
      onclick="Button3_Click" />
       
      protected void Page_Load(object sender, EventArgs e)
      {
          
      if (!IsPostBack)
          {
              MultiView1.ActiveViewIndex = 0;
          }
      }
      protected void Button3_Click(object sender, EventArgs e)
      {
          
      if (MultiView1.ActiveViewIndex < MultiView1.Views.Count - 1)
          {
              MultiView1.ActiveViewIndex++;
          }
      }
  8. Wizard
    • The Wizard control can be used when there is a need for step-by-step logic. This control allows for a far greater degree of customization than does the MultiView control. As an example add the Wizard control and add some controls to its steps:
    • This control has some interesting events, e.g. FinishButtonClick:
      protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
      {
          Wizard1.Visible =
      false;
          Literal1.Visible =
      true;
      }
    • There are many formatting options available for the Wizard button. The easiest way is probably to start from the AutoFormat option:
  9. PlaceHolder
    • This control is a placeholder to interject objects dynamically into the Web page. It does not produce any visible output and is only used as a container for other controls on the Web page. Its Controls collection can be used as for any container.

      protected void Button4_Click(object sender, EventArgs e)
      {
          
      Literal literal = new Literal();
          literal.Text =
      string.Format("{0}<br>", DateTime.Now.ToString());
          PlaceHolder1.Controls.Add(literal);
      }

      Run the page. Note that after clicking the 'Add a Literal to the PlaceHolder' button, a new Literal appears in the place reserved by the PlaceHolder. Note also that after the second clicking on the button, the previously added text disappears. The reason of this behaviour is simple - each time the request is processed by the ASP.NET engine, the PlaceHolder control (as any other control) is initialized. Initialization of the PlaceHolder control used in this example does nothing - no controls are added to it. Later, after initialization and loading, the event handler adds one control, and this is the only one visible control.
  10. HiddenField
    • This control can be used to store some data at the level of a single page. For example, it can be used to solve the problem from the previous point - to allow to display all values added to the PlaceHolder control.
    • Add the HiddenField control to the page. (The place does not matter - the control is invisible.)
      <asp:HiddenField ID="HiddenField1" runat="server" />
    • Modify code in the Load event of the page and the Click event of the button:
      protected void Page_Load(object sender, EventArgs e)
      {
          
      if (!IsPostBack)
          {
              
      // previous code    }
          
      else
          {
              
      string[] texts = HiddenField1.Value.Split(';');
              
      foreach (string text in texts)
              {
                  AddToPlaceHolder(text);
              }
          }
      }
      private void AddToPlaceHolder(string text)
      {
          
      Literal literal = new Literal();
          literal.Text = text +
      "<br>";
          PlaceHolder1.Controls.Add(literal);
      }
      private void AddToHiddenField(string text)
      {
          
      if (HiddenField1.Value.Length > 0)
          {
              HiddenField1.Value +=
      ';';
          }
          HiddenField1.Value += text;
      }
      protected void Button4_Click(object sender, EventArgs e)
      {
          
      string text = DateTime.Now.ToString();
          AddToPlaceHolder(text);
          AddToHiddenField(text);
      }
      Run the page and make a few postbacks using the Button4, note that values in the PlaceHolder control are kept.
    • Very common usage of the HiddenField control is passing data from the server to the client-side code written in JavaScript and vice-versa.
[Source code]

ASP.NET Server Controls

Goals:
  • Present simple ASP.NET server controls.
Steps:
  1. Create a new ASP.NET Web Application project in Visual Studio.
  2. Label
    • Add a Label control to the page, modify its Text property.
    • Run the application and take a look at the source code of generated HTML code, note that the Label control was rendered as the span tag:
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      
      <html xmlns="http://www.w3.org/1999/xhtml" >
      <head><title>
      
      </title></head>
      <body>
          <form name="form1" method="post" action="Default.aspx" id="form1">
      <div>
      <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJOTczNTMyNjI5ZGQ+tlIH8gC3zZwd0romTjnrPAqrbg==" />
      </div>
          <div>
              <span id="Label1">This is a label</span>
          </div>
          </form>
      </body>
      </html>
    • An interesting feature of the Label control is ability to define a hot-key for an assigned server control. Add Label and TextBox controls to the page and set the AccessKey and AssociatedControlID properties of the Label:
    • This time, the rendered HTML code contains the Label tag:
          <label for="TextBox1" id="Label2" accesskey="T">
              Label associated with <u>T</u>extBox (use Alt+T to move the focus to 
              the TextBox)
          </label>
          <input name="TextBox1" type="text" id="TextBox1" />
  3. Literal
    • The Literal control is similar to the Label control, but it is rendered as a plain text, without additional tags. Add 2 Literal controls to the page and set their Text property to 'Normal text, <b>bold</b> text'. For the second control set also the Mode property to 'Encode':
    • Check the output HTML code, note the difference in rendering '<' and '>' characters:
       Normal text, <b>bold</b> text.
      <br />
      Normal text, &lt;b&gt;bold&lt;/b&gt; text.
  4. TextBox
    • Add 3 TextBox controls to the page. Leave the first one default. Set the TextMode property of the 2nd one to 'Password'. Set the TextMode property of the 3rd one to 'MultiLine' and set also its Width and Height properties:
    • Look at the generated HTML code and note differences:
       Simple textbox:
      <input name="TextBox2" type="text" id="TextBox2" />
      <br />
      Password textbox:
      <input name="TextBox3" type="password" id="TextBox3" />
      <br />
      Multiline textbox:
      <textarea name="TextBox4" rows="2" cols="20" id="TextBox4" style="height:100px;width:200px;"></textarea>
    • The TextBox control has the TextChanged event triggered when the user moves the focus outside the text box. Add an event handler for this event to the TextBox, in response for this event modify the control's text:
      protected void TextBox2_TextChanged(object sender, EventArgs e)
      {
          TextBox2.Text +=
      " --- MODIFIED!";
      }
    • To make it work, the AutoPostBack property of the TextBox must be changed to true.
    • Run and test the page. Note that the postback is sent when the focus leaves the text box.
    • It is also possible to do something dynamically without a postback, using JavaScript. Add the following code to the page (e.g. between the header and the body of the page):
      <script>
      function
      tbChangedJS() {
          
      return confirm("Should I postback?");
      }
      </script>
      For the TextBox, add the onchange property with JavaScript code calling this method:
      <asp:TextBox ID="TextBox2" runat="server" AutoPostBack="True"
          
      ontextchanged="TextBox2_TextChanged"
          onchange="if (!tbChangedJS()) return;" >
      </
      asp:TextBox>
      To understand how it works, see the output HTML code:
      <input name="TextBox2" 
             type="text" 
             onchange="if (!tbChangedJS()) return;setTimeout('__doPostBack(\'TextBox2\',\'\')', 0)" 
             onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;" 
             id="TextBox2" />
      Note that the default TextBox's rendering adds some JavaScript code.
  5. Button
    • Add the Button controls to the page, and double-click it in the Design view - the onclick event is automatically generated:

      Add code modifying the Button's text in response for this event:
      protected void Button1_Click(object sender, EventArgs e)
      {
          Button1.Text +=
      " - clicked!";
      }
      Compile and test the page.
    • It is also possible to fire the JavaScript click event before the postback, add the following code to the Button1:
      onclientclick="alert('Hello from the Button1');"
    • It is possible to attach one common ASP.NET click event handler to more than 1 button. Add 2 new buttons and a Literal to the page:
      <asp:Button ID="Button2" Runat="server" Text="Button 2"
          
      OnCommand="Button_Command" CommandName="DoSomething2" />
      <
      asp:Button ID="Button3" Runat="server" Text="Button 3"    OnCommand="Button_Command" CommandName="DoSomething3" />
      <
      asp:Literal ID="Literal3" Runat="server"/>
      Add the following code to the code-behind file:
      protected void Button_Command(Object sender, CommandEventArgs e)
      {
          
      switch (e.CommandName)
          {
              
      case "DoSomething2":
                  Literal3.Text =
      "Button 2 was selected";
                  
      break;
              
      case "DoSomething3":
                  Literal3.Text =
      "Button 3 was selected";
                  
      break;
          }
      }
  6. LinkButton
    • The LinkButton control is a button rendered as a hyperlink:
  7. ImageButton
    • The ImageButton control has all the Button's functionality plus possibility to check coordinates of clicked point. Add the following markup code:
      <asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="sample.jpg"
          
      onclick="ImageButton1_Click" />
      <
      asp:Literal ID="Literal4" runat="server"></asp:Literal>
      and C# code:
      protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
      {
          Literal4.Text =
      string.Format("Click at ({0}, {1})", e.X, e.Y);
      }
  8. HyperLink
    • Hyperlinks generated by the HyperLink control can use text or image:
    • This control is rendered as a <a> tag:
       <a id="HyperLink1" href="http://www.google.com">HyperLink to google</a>
      <br />
      <a id="HyperLink2" href="http://www.google.com"><img src="sample.gif" style="border-width:0px;" /></a>
  9. DropDownList
    • Items of the DropDownList control can be initialized statically (the Visual Studio Designer can be used for the Items property, instead of manual writing values):
    • Additionally, the content can be modified dynamically (Default.aspx.cs file):
      protected void Page_Load(object sender, EventArgs e)
      {
          
      if (!IsPostBack)
          {
              DropDownList1.Items.Remove(
      "Second");
              DropDownList1.Items.Add(
      "Fourth");
              DropDownList1.SelectedValue =
      "Third";
          }
      }
      To understand, why checking of the IsPostBack flag is necessary, comment it out, run the page and make some postbacks using other controls - the Fourth item will appear many times on the list.
    • The DropDownList control automatically forces a postback in case of changing its selected value, when the AutoPostBack property is set to true:
      AutoPostBack="True" onselectedindexchanged="DropDownList1_SelectedIndexChanged"
      Code for the event:
      protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
      {
          DropDownList1.SelectedItem.Text +=
      " - selected!";
      }
  10. ListBox
    • The ListBox control has similar functionality to the DropDownList control, but additionally more than one item can be selected when the SelectionMode property is set to 'Multiple':

      protected void Button4_Click(object sender, EventArgs e)
      {
          
      StringBuilder sb = new StringBuilder("Selected: ");
          
      foreach (int i in ListBox1.GetSelectedIndices())
          {
              sb.AppendFormat(
      "{0} ", ListBox1.Items[i].Text);
          }
          Literal5.Text = sb.ToString();
      }
  11. CheckBox
    • The CheckBox control can also force a postback, when the AutoPostBack property is set to true. Additionally, text alignment can be changed:

      protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
      {
          CheckBox1.Text +=
      " - checked!";
      }
  12. CheckBoxList
    • This control is very helpful when there is a need to display a list of items with checkboxes to allow to select presented items. Instead of creating many CheckBox controls, one CheckBoxList control can be used:
    • Items can be added using the Items property (either statically in the Visual Studio Designer or dynamically in the source code), or bound using the DataSource property:
      protected void Page_Load(object sender, EventArgs e)
      {
          
      if (!IsPostBack)
          {
              DropDownList1.Items.Remove(
      "Second");
              DropDownList1.Items.Add(
      "Fourth");
              DropDownList1.SelectedValue =
      "Third";

              
      string[] items = new string[] { "First", "Second", "Third", "Fourth", "Fifth" };
              CheckBoxList1.DataSource = items;
              CheckBoxList1.DataBind();
          }
      }
      protected void Button5_Click(object sender, EventArgs e)
      {
          StringBuilder sb = new StringBuilder("Selected: ");
          foreach (ListItem li in CheckBoxList1.Items)
          {
              if (li.Selected)
              {
                  sb.AppendFormat("{0} ", li.Text);
              }
          }
          Literal6.Text = sb.ToString();
      }
      Setting the DataSource property does not makes the action of binding data, the DataBind method must be called explicitly.
  13. RadioButton
    • For the RadioButton controls the GroupName property is crucial. For example, in the following code the 1st and 2nd RadioButton controls can be selected simultaneously because their values of the GroupName property differ:
  14. RadioButtonList
    • This control is very similar to the CheckBoxList control, the only difference is that in the RadioButtonList it is impossible to select more than 1 item.
  15. BulletedList  
    • The BulletedList control can be an alternative for the RadioButtonList control. It can display a list of items:

      and catch a click on an item:
      protected void BulletedList1_Click(object sender, BulletedListEventArgs e)
      {
          Literal7.Text =
      "Clicked: " + BulletedList1.Items[e.Index].Text;
      }
  16. Image
    • The Image control is rendered as a static image, which does not support handling user clicks.
  17. ImageMap
    • It enables to turn an image into a navigation menu. Rectangle, circle, and polygon hotspots (easy to define using the Visual Studio Designer) can be used to catch clicks. In the following example one rectangle (pointing to http://www.google.com ) and one circle hotspot (causes a postback) are used:

      Note, that the red circle and rectangle are statically drawn on the image.
      protected void ImageMap1_Click(object sender, ImageMapEventArgs e)
      {
          
      if (e.PostBackValue == "theCircle")
          {
              Literal8.Text =
      "Circle clicked!";
          }
      }
[Source code]