| 0 comments ]

This short article demonstrates how to change the opacity of an image when the user hovers the mouse over an image.
Note that for demonstration purposes, I have included jQuery and CSS code in the same page. Ideally, these resources should be created in separate folders for maintainability.
Let us quickly jump to the solution and see how we can change the opacity of an image.

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Change Image Opacity on Hover</title>
    <style type="text/css">
    .imgOpa
    {
        height:250px;
        width:250px;
        opacity:0.3;
        filter:alpha(opacity=30);
    }
    </style>
    <script type="text/javascript"
     src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
    </script>
   
    <script type="text/javascript">
        $(function() {
            $('.imgOpa').each(function() {
                $(this).hover(
                    function() {
                        $(this).stop().animate({ opacity: 1.0 }, 800);
                    },
                   function() {
                       $(this).stop().animate({ opacity: 0.3 }, 800);
                   })
                });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h2>Hover over an Image to change its Transparency level</h2>
        <br />
        <asp:Image ID="Image1" runat="server"
            ImageUrl="../images/1.jpg" class="imgOpa" />
        <asp:Image ID="Image2" runat="server"
            ImageUrl="../images/2.jpg" class="imgOpa" />
        <asp:Image ID="Image3" runat="server"
            ImageUrl="../images/3.jpg" class="imgOpa" />
        <asp:Image ID="Image4" runat="server"
            ImageUrl="../images/4.jpg" class="imgOpa" />
    </div>
    </form>
</body>
</html>
In this example, observe that the images have a class attribute ‘imgOpa’. The definition of the CSS class is as shown here:
.imgOpa
    {
        height:250px;
        width:250px;
        opacity:0.3;
        filter:alpha(opacity=30);
    }
When the images are loaded, they are in a semitransparent state. In Firefox, Chrome and Safari, we use the opacity:n property for transparency. The opacity value can be from 0.0 - 1.0, where a lower value makes the element more transparent.
In IE 7 and later, we use filter:alpha(opacity=n) property for transparency, where the opacity value can be from 0-100.
When the user hovers the mouse over a semitransparent image, we use the jQuery hover() method to animate the opacity property from 0.3 to 1.0, thereby creating a cool effect on the images. The code to achieve this effect is shown below:
$(this).hover(
    function() {
        $(this).stop().animate({ opacity: 1.0 }, 800);
    },
   function() {
       $(this).stop().animate({ opacity: 0.3 }, 800);
   })
});
I hope you found this article useful and I thank you for viewing it

| 0 comments ]

This short article demonstrates how to create a watermark effect on your TextBox and display instructions to users, without taking up screen space.
Note that for demonstration purposes, I have included jQuery code in the same page. Ideally, these resources should be created in separate folders for maintainability.
Let us quickly jump to the solution and see how we can create a watermark effect on your TextBox using client-side code.

<!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 id="Head1" runat="server">
    <title>TextBox WaterMark</title>
    <script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
    </script>  
   
    <style type="text/css">
    .water
    {
         font-family: Tahoma, Arial, sans-serif;
         color:gray;
    }
    </style>
   
    <script type="text/javascript">
        $(function() {
 
            $(".water").each(function() {
                $tb = $(this);
                if ($tb.val() != this.title) {
                    $tb.removeClass("water");
                }
            });
 
            $(".water").focus(function() {
                $tb = $(this);
                if ($tb.val() == this.title) {
                    $tb.val("");
                    $tb.removeClass("water");
                }
            });
 
            $(".water").blur(function() {
                $tb = $(this);
                if ($.trim($tb.val()) == "") {
                    $tb.val(this.title);
                    $tb.addClass("water");
                }
            });
        });       
 
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div class="smallDiv">
     <h2>TextBox Watermark Demonstration</h2>    <br />          
        <asp:TextBox ID="txtFNm" class="water" Text="Type your First Name"
        Tooltip="Type your First Name" runat="server"></asp:TextBox><br />
        <asp:TextBox ID="txtLNm" class="water" Text="Type your Last Name"
        Tooltip="Type your Last Name" runat="server"></asp:TextBox>
        <br /><br />
        <asp:Button ID="btnSubmit" runat="server" Text="Submit" />
        <br /><br />
        Tip: Click on the TextBox to start typing. The watermark
        text disappears.
    </div>
    </form>
</body>
</html>
The code shown above adds the “watermark” behavior to controls marked with the ‘class=water’ attribute. When the user loads the page, a watermarked textbox displays a message to the user. As soon as the watermarked textbox receives focus and the user types some text, the watermark goes away. This technique is a great space saver as you can use it to provide instructions to the user, without using extra controls that take up valuable space on your form.
The ‘Tooltip’ attribute applied to the textbox is crucial to this example. The ‘Tooltip’ gets rendered as ‘title’. Observe the code, as we use this ‘title’ property to compare it to the textbox value and remove the watermark css, when the textbox control gains focus
$(".water").focus(function() {
                $tb = $(this);
                if ($tb.val() == this.title) {
                    $tb.val("");
                    $tb.removeClass("water");
                }
            });
Similarly when the user moves focus to a different control without entering a value in the textbox, we add the watermark css again.

$(".water").blur(function() {
                $tb = $(this);
                if ($.trim($tb.val()) == "") {
                    $tb.val(this.title);
                    $tb.addClass("water");
                }
            });
The water class declared in Demos.css looks like this:
.water
{
     font-family: Tahoma, Arial, sans-serif;
     font-size:75%;
     color:gray;
}
When the user enters the First/Last Name and submits the form, the watermark behavior is no more needed to be displayed. This is achieved by comparing the ‘title’ with the ‘value’ of the textbox. If the ‘value’ does not match the ‘title’, this indicates that the user has entered some value in the textboxes and submitted the form. So in this case we remove the watermark appearance.
$(".water").each(function() {
                $tb = $(this);
                if ($tb.val() != this.title) {
                    $tb.removeClass("water");
                }
            });

| 0 comments ]

In this post I’ll show how to use jQuery to automatically convert all email addesses from static text into a mailto link.
Consider the following table which contains a person’s details including their email address.






Using jQuery I can easily find table cells that contain an email address by using a regular expression and then convert the address into a mailto link:
$().ready(function() {
    var regEx = /(\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)/;

    $("table td").filter(function() {
        return $(this).html().match(regEx);
    }).each(function() {
        $(this).html($(this).html().replace(regEx, "<a href=\"mailto:$1\">$1</a>"));
    });
});

First I’ve defined my email regular expression. I have also made sure the entire expression is in brackets, this sets up a regular expression group for the whole thing which I use when doing the replace.
For my example I’m only going to replace email addresses within a TD tag so my selector first gets these elements. I next use the filter function to only select the email address content from the TD by using the JavaScript match function with my email regular expression. I then iterate over the collection of elements and use the JavaScript replace function to replace the static email address with a mailto hyperlink to the same email address.
In my replace string I’m using $1, which will output the matching text from the original string from the first grouping in my regular expression. As I said earlier I put brackets around my entire regular expression so that the first grouping it the whole thing. This means that $1 will output the matched email address.
Now when I run my project the email addresses are automatically mailto links:

| 0 comments ]

This article demonstrates how to autoscroll a multiline textbox both upwards and downwards using jQuery 1.3.2.

Note that for demonstration purposes, I have included jQuery code in the same page. Ideally, these resources should be created in separate folders for maintainability. The code shown below has been tested on IE7, Firefox 3, Chrome 2 and Safari 4
Let us quickly jump to the solution and see how to AutoScroll a multiline textbox.

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>AutoScroll a Multiline TextBox</title>
    <script type="text/javascript"
     src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
    </script>
 
   
    <script type="text/javascript">
        $(function() {
            var $tb = $('textarea[id$=tb1]');
 
            $('input[id$=btnScroll]').toggle(
            function(e) {
                e.preventDefault();
                scrollArea($tb, $tb[0].scrollHeight);
            },
            function(e) {
                e.preventDefault();
                scrollArea($tb, 0);
            });
        });
 
        function scrollArea(ctrl, ht) {
            ctrl.animate({ scrollTop: ht }, 1000);
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div class="smallDiv">
        <h2>Scroll the box contents by clicking on the Button</h2>
        <br /><br />
        <asp:TextBox ID="tb1" runat="server" TextMode="MultiLine"
        Text="Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem
        Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum
        Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum
        Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum
        Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum"
        Rows="5"/>
        <br />
        <asp:Button ID="btnScroll" runat="server" Text="Scroll"/>
        <br /><br />
        Tip: The Text can be scrolled both downwards and upwards.
    </div>
    </form>
</body>
</html>

When the user clicks on the button (btnScroll), we toggle the click behavior. On the first click, we cancel the postback by using e.preventDefault() and then call a function called scrollArea() passing in the textarea and the scrollHeight. The code $tb[0].scrollHeight is for scrolling downwards

e.preventDefault();
scrollArea($tb, $tb[0].scrollHeight);
When the user clicks the button (btnScroll) again, the postback is cancelled and the scrollHeight is set to 0 (zero). This is done for scrolling upwards.

e.preventDefault();
scrollArea($tb, 0);
The scrollArea() function accepts the textarea that is to be scrolled as well as the scrollHeight. We then animate the scrollTop property to scroll upwards/downwards depending on the height parameter. The duration of the animation is set to 1000 milliseconds which provides a smooth scrolling effect

function scrollArea(ctrl, ht) {
    ctrl.animate({ scrollTop: ht }, 1000);
}

The code here assumes that you are not scrolling the textarea manually and then clicking the Scroll button.
I hope you found this article useful and I thank you for viewing it.

| 1 comments ]

Recently a new version of jQuery was released. This version is 1.4. As with any new version, ultimately you see what used to take you several lines of code, now rolled up into a single line of code. I'm going to demonstrate a question I've been asked many times on forums and that is how to move selected items from one &lgt;select> element to another. I'll show you how you could do it using jQuery 1.3.2 and how to minimize the code by using the new 1.4 library. Before we begin, the new version can be found here.

The HTML
The HTML for this is pretty straight forward. It's simply two elements side by side with two buttons between them. Here's what it looks like:

<form method="get">             
      <select id="SelectLeft" multiple="multiple">
            <option value="1">Australia</option>
            <option value="2">New Zealand</option>
            <option value="3">Canada</option>
            <option value="4">USA</option>
            <option value="5">France</option>
      </select>
           
      <input id="MoveRight" type="button" value=" >> " />
      <input id="MoveLeft" type="button" value=" << " />
       
      <select id="SelectRight" multiple="multiple">          
      </select>
</form>














jQuery 1.3.2

Below is the code to move the selected items from each <select> element.
<script language="javascript" type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>   
    <script language="javascript" type="text/javascript">
        $(function() {
            $("#MoveRight,#MoveLeft").click(function(event) {
                var id = $(event.target).attr("id");
                var selectFrom = id == "MoveRight" ? "#SelectLeft" : "#SelectRight";
                var moveTo = id == "MoveRight" ? "#SelectRight" : "#SelectLeft";
 
                var selectedItems = $(selectFrom + "option:selected");
                var output = [];               
                $.each(selectedItems, function(key, e) {                   
                  output.push('<option value="' + e.value + '">' + e.text + '</option>');
                                });
               
                $(moveTo).append(output.join(""));               
                selectedItems.remove();
            });
        });
    </script>

I've bound one event handler for the button clicks. To decide which direction the selected items should go, I'm using the ID of the button that fired the event:

var id = $(event.target).attr("id");
var selectFrom = id == "MoveRight" ? "#SelectLeft" : "#SelectRight";
var moveTo = id == "MoveRight" ? "#SelectRight" : "#SelectLeft";

Next I create an empty array and loop through every selected item and add it to the end of the array:

var output = [];               
$.each(selectedItems, function(key, e) {                   
      output.push('<option value="' + e.value + '">' + e.text + '</option>');
});

Then I append it to the end of the <select> element and remove the moved items:
$(moveTo).append(output.join(""));
selectedItems.remove();

Overall I think that's a good approach. In jQuery 1.4 we can make this better!

jQuery 1.4

In the new jQuery library, the team has introduced a new function called toArray. This retrieves all the DOM elements contained in the jQuery set, as an array. So here's the code below:

<script language="javascript" type="text/javascript" src="http://code.jquery.com/jquery-1.4.1.min.js"></script>
    <script language="javascript" type="text/javascript">
        $(function() {
            $("#MoveRight,#MoveLeft").click(function(event) {
                var id = $(event.target).attr("id");
                var selectFrom = id == "MoveRight" ? "#SelectLeft" : "#SelectRight";
                var moveTo = id == "MoveRight" ? "#SelectRight" : "#SelectLeft";
 
                var selectedItems = $(selectFrom + " :selected").toArray();
                $(moveTo).append(selectedItems);
                selectedItems.remove;
            });
        });
    </script>  

The first thing you'll notice is the code has been reduced. Thanks to the toArray function, I have eliminated the need to loop through the selected items. Now they're returned as an array

var selectedItems = $(selectFrom + " :selected").toArray();

And to add them to the <select> element, I no longer need to use the join function, I simply append them: $(moveTo).append(selectedItems);
 Nice and simple!

| 1 comments ]

Repeater control is one of the light weight control when compared to the other databound controls. It provides more flexibility on the layout of data displayed and the control itself will not render any additional HTML like GridView and DataList control do. It only renders the HTML we specified in the template columns which makes it light weight when compared to other controls.

Repeater control as such will not provide edit/update functionalities for the data.

In this article, we will overcome this difficulty and provide an edit update feature similar to GridView control using the powerful jQuery library and Ajax.
Refer the below figure to understand better.







Steps
  • Open Visual Studio 2008, Click File >Website and choose ASP.Net Website.
  • Select a language of your choice. I have selected C#. You can name your website as per your need.
  • Drag a Repeater control from the data tab of the Visual Studio.
  • You can add a Sql server Express database in App_Data Folder and create a table called Employee with all the necessary fields. Enter some sample data to display in the Repeater control.
  • Specify the HeaderTemplate, ItemTemplate and FooterTemplate to display the employee data in tabular format. Bind the Repeater control from codebehind by fetching employee detail from the express database we have created in App_Data folder.
Refer the below code,
ASPX
<asp:Repeater ID="rpEmployee" runat="server">
    <HeaderTemplate>
    <table border="0" ID="tblEmployee">
        <tr id="Tr2" runat="server" style="">
            <th id="Th1">
            </th>
            <th id="Th2">
            EmpID</th>
            <th id="Th3">
            EmpName</th>
            <th id="Th4">
            Department</th>
            <th id="Th5">
            Age</th>
            <th id="Th6">
            Address</th>
       </tr>                   
    </HeaderTemplate>
    <ItemTemplate>
      <tr ID='<%# Eval("EmpID") %>'>
                    <td>                       
                        <input type="button" value="Edit"/>
                        <input type="button" value="Update" style="display:none" />
                        <input type="button" value="Cancel" style="display:none" />
                    </td>
                    <td>
                       <%# Eval("EmpID") %>
                    </td>
                    <td>
                        <%# Eval("EmpName") %>
                    </td>
                    <td>
                        <%# Eval("Department") %>
                    </td>
                    <td>
                        <%# Eval("Age") %>
                    </td>
                    <td>
                      <%# Eval("Address") %>
                    </td>
       </tr>   
    </ItemTemplate>
    <FooterTemplate>
    </table>
    </FooterTemplate>
    </asp:Repeater>

CodeBehind
protected void Page_Load(object sender, EventArgs e)
    {
            rpEmployee.DataSource = GetEmployee("Select * from Employee");
            rpEmployee.DataBind();
    }
    public DataTable GetEmployee(string query)
    {
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString);
        SqlDataAdapter ada = new SqlDataAdapter(query, con);
        DataTable dtEmp = new DataTable();
        ada.Fill(dtEmp);
        return dtEmp;
    }
Execute the page and you can see the employee details in tabular view with an edit button.

Next, we will make the Repeater control’s row editable similar to the inbuilt edit feature of GridView control using jQuery library.

Providing Edit Update Feature

When the user clicks the edit button, we will hide the edit button and enable update & cancel button for that row. Just like GridView control, we will also populate the table cell value of the editing row in a textbox control to edit. After editing the value and on clicking Update button, we call a page method called UpdateEmployee() to update the employee details in the database using the jQuery’s ajax() method.

First, we will develop our page method UpdateEmployee() in our codebehind to update the employee details that is passed to it from jQuery’s ajax method.

[WebMethod]
   public static string UpdateEmployee(string empid,string name,string dept,string age,string address)  
    { 
        string UpdateQuery = "UPDATE [Employee] SET [EmpName] = @name, [Department] =  @dept, [Age] = @age, [Address] = @address WHERE [EmpID] = @empid";
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString);
        con.Open();
        SqlCommand com = new SqlCommand(UpdateQuery, con);
        com.Parameters.Add("@name", SqlDbType.VarChar, 50).Value = name;
        com.Parameters.Add("@dept", SqlDbType.VarChar, 50).Value = dept;
        com.Parameters.Add("@age", SqlDbType.Int, 4).Value = age;
        com.Parameters.Add("@address", SqlDbType.VarChar, 50).Value = address;
        com.Parameters.Add("@empid", SqlDbType.Int, 4).Value = empid;       
        int n = com.ExecuteNonQuery();
        con.Close();
 
        return n.ToString();
    }


As we all know, a page method should be public static and should be decorated with WebMethod attribute. You need to include the System.Web.Services namespace for the WebMethod attribute to work. To know more about page methods and consuming it from jQuery, please read Using JQuery in ASP.Net AJAX Applications – Part 1.

Next, we will move to the client side part of our implementation where we can provide an editing option to the user. Refer the above FAQ’s to integrate jQuery library into our project.

The following jQuery code will help us to do the rest of our operations.

<script src="_scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
    <script language="javascript">
        $(function() {
            $("#tblEmployee > tbody > tr ").each(function() {
                var TRID = $(this).attr("id");
                $(this).find("td:first > input[value=Edit]").click(function() {                   
                    ResetOtherRowEdit();
                    ChangeTableCellToTextbox(TRID);
                    $(this).hide();
                    return false;
                });
 
                $(this).find("td:first > input[value=Update]").click(function() {
                    UpdateRow(TRID);
                });
 
                $(this).find("td:first > input[value=Cancel]").click(function() {
                    CancelEdit(TRID);
                });
 
            });
        });
 
        function ChangeTableCellToTextbox(RowID) {
            $("#" + RowID + "> TD").filter(function() {
                if ($(this).find("INPUT").html() == null & !($(this).is(":nth-child(2)"))) {
                    return true;
                }
            }).each(function() {
                var TDvalue = $(this).html();               
                var replacevalue = "<input type=text value=\"" + TDvalue + "\"></input>";
                $(this).html(replacevalue);
            });
 
            $("#tblEmployee > tbody > tr[id="+ RowID +"] > td:first> input[value=Update]").show();
            $("#tblEmployee > tbody >  tr[id=" + RowID + "] > td:first> input[value=Cancel]").show();
        }
 
        function UpdateRow(RowID) {           
            var empid = $("#" + RowID + "> TD:nth-child(2)").html();
            var empname =$("#" + RowID + "> TD:nth-child(3) > input[type=text]").val();
            var dept = $("#" + RowID + "> TD:nth-child(4) > input[type=text]").val();
            var age = $("#" + RowID + "> TD:nth-child(5) > input[type=text]").val();
            var address =$("#" + RowID + "> TD:nth-child(6) > input[type=text]").val();
 
            var options = {
                type: "POST",
                url: "RepeaterEdit.aspx/UpdateEmployee",
                data: "{\"empid\":\"" + empid + "\",\"name\":\"" + empname + "\",\"dept\":\"" + dept + "\",\"age\":\"" + age + "\",\"address\":\"" + address + "\"}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function(response) {
                    if (response.d != "") {
                        if (response.d == "1") {
                            alert("Updation Successful");
                            CancelEdit(RowID);
                        }
                        else {
                            alert("Updation failed!");
                        }
                    }
                }
            };
            //Call the PageMethods
            $.ajax(options);         
        }
 
        function CancelEdit(RowID) {
            $("#" + RowID + "> TD").filter(function() {
                if ($(this).find("INPUT[type=text]").val() != null) {
                    return true;
                }
            }).each(function() {              
                $(this).html($(this).find("INPUT[type=text]").val());
            });
          $("#tblEmployee > tbody > tr[id=" + RowID + "] > td:first> input[value=Update]").hide();
          $("#tblEmployee > tbody >  tr[id=" + RowID + "] > td:first> input[value=Cancel]").hide();
          $("#tblEmployee > tbody >  tr[id=" + RowID + "] > td:first> input[value=Edit]").show();
      }
 
      function ResetOtherRowEdit() {
          $("#tblEmployee > tbody > tr ").each(function() {
              var TRID = $(this).attr("id");
              if ($(this).find("td:first > input[value=Update]").css("display") == "inline") {
                  CancelEdit(TRID);
              }
          });
      }       
    </script>

Execute the page and see it in action.

The ajax() method uses JSON and POST method to send the employee data to the page method. Once the data is updated successful, the page method will return 1 which indicates success(No of rows affected in ExecuteNonQuery() in our case). On success, you will see a success alert message.

Things to consider

  • The above jQuery code will call the page method even if you have not changed the details in any cell. You can modify UpdateRow() method to call the page method only if the value is changed by comparing with initial table cell value.
  • The above jQuery code will change the table cell to textbox by populating its value to textbox directly. You can get the employee detail for that row using the employeeid from the server to get the latest data. You can write one more page method that can return the employee detail in JSON format and populate the textboxes.

| 0 comments ]

This is an introduction to Linq to XML showing how to read, insert, update and delete from an XML file.
First of all lets look at the XML file I will be using:

<?xml version="1.0" encoding="utf-8"?>
<Customers>
 <Customer ID="1">
  <Forename>Joe</Forename>
  <Surname>Stevens</Surname>
  <DOB>31/01/1983</DOB>
  <Location>Sydney</Location>
 </Customer>
 <Customer ID="2">
  <Forename>Tom</Forename>
  <Surname>Male</Surname>
  <DOB>02/02/1977</DOB>
  <Location>Brisbane</Location>
 </Customer>
 <Customer ID="3">
  <Forename>Emily </Forename>
  <Surname>Stevens</Surname>
  <DOB>14/01/1988</DOB>
  <Location>Sydney</Location>
 </Customer>
 <Customer ID="4">
  <Forename>Lee</Forename>
  <Surname>Phipps</Surname>
  <DOB>05/12/1982</DOB>
  <Location>Melbourne</Location>
 </Customer>
 <Customer ID="5">
  <Forename>Saul</Forename>
  <Surname>Stevens</Surname>
  <DOB>02/08/1984</DOB>
  <Location>Perth</Location>
 </Customer>
</Customers>

As you can see it’s a very simple list of customers. In my project I have also created a Customer class to represent each customer:

public class Customer
{
    public int ID { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string DOB { get; set; }
    public string Location { get; set; }
}

Firsly I want to be able to select a single customer based on their ID. The following method shows how to load the XML file and query it to find the customer we want, and return the data as a single Customer object:

public static Customer GetCustomer(int customerID)
{
    XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

    return (from c in data.Descendants("Customer")
            where c.Attribute("ID").Value.Equals(customerID.ToString())
            select new Customer()
            {
                ID = Convert.ToInt32(c.Attribute("ID").Value),
                Forename = c.Element("Forename").Value,
                Surname = c.Element("Surname").Value,
                DOB = c.Element("DOB").Value,
                Location = c.Element("Location").Value

            }).FirstOrDefault();
}

Firstly the XML document is loaded using the XDocument class. I then use Linq to look at all the Customer elements and find the one where the ID attribute matches the value passed to the method. The Customer object is then populated with each element within the Customer element.
I’ve created a simple web form that uses an ObjectDataSource with this method to display a customer based on the ID in the query string:

<asp:DetailsView
    ID="dvCustomer"
    DataSourceID="odsCustomer"
    runat="server">
</asp:DetailsView>

<asp:ObjectDataSource
    ID="odsCustomer"
    TypeName="LinqToXml.Data.DAL"
    SelectMethod="GetCustomer"
    runat="server">
    <SelectParameters>
        <asp:QueryStringParameter Name="customerID" QueryStringField="id" DefaultValue="1" />
    </SelectParameters>
</asp:ObjectDataSource>
The page creates the following table:







To get a list of all customers is very similar to getting a single customer, although the method will return a generic list of Customer objects:

public static List<Customer> GetCustomers()
{
    XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

    return (from c in data.Descendants("Customer")
            orderby c.Attribute("Surname")
            select new Customer()
            {
                ID = Convert.ToInt32(c.Attribute("ID").Value),
                Forename = c.Element("Forename").Value,
                Surname = c.Element("Surname").Value,
                DOB = c.Element("DOB").Value,
                Location = c.Element("Location").Value

            }).ToList();
}

Here I am also using the orderby operator to order the results by the value of the Surname element.
I have a single method called Save which is used for both inserting and updating. It accepts a Customer object and performs an insert or update depending on the ID value of that object:
public static void Save(Customer customer)
{
    XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

    if (customer.ID > 0)
    {
        XElement customerElement = data.Descendants("Customer").Where(c => c.Attribute("ID").Value.Equals(customer.ID.ToString())).FirstOrDefault();
        if (customerElement != null)
        {
            customerElement.SetElementValue("Forename", customer.Forename);
            customerElement.SetElementValue("Surname", customer.Surname);
            customerElement.SetElementValue("DOB", customer.DOB);
            customerElement.SetElementValue("Location", customer.Location);

            data.Save(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));
        }
    }
    else
    {
        XElement newCustomer = new XElement (   "Customer",
                                                new XElement("Forename", customer.Forename),
                                                new XElement("Surname", customer.Surname),
                                                new XElement("DOB", customer.DOB),
                                                new XElement("Location", customer.Location)
                                            );

        newCustomer.SetAttributeValue("ID", GetNextAvailableID());

        data.Element("Customers").Add(newCustomer);
        data.Save(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));
    }
}

In this method I load the XML document as before and then check the value of customer.ID to see whether to insert or update.

If the value is greater than zero then it is an update. Firstly I get the element matching the ID using the Where extension method and a lambda expression using the given ID. If the element is found (not null), I use the SetElementValue method to update the values of the child elements with their new values. After this is done I call save on the XDocument and pass the URL on the original XML file to update it.

If customer.ID is zero then I know this is a new record and I need to perform an insert. This is done by creating a new XElement with the name Customer, then by creating a list of XElements for the children. I then set the ID attribute on the Customer element by calling a method called GetNextAvailableID which I’ll explain in a moment. Now my element is ready to be inserted so using my XDocument I use the Element method to get the Customers element and the Add method to add my new element to it. As with the update I then need to call the save method on the XDocument.

The GetNextAvailableID method simply finds the highest ID used in the XML document and adds one to it:

private static int GetNextAvailableID()
{
XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

return Convert.ToInt32(
(from c in data.Descendants("Customer")
orderby Convert.ToInt32(c.Attribute("ID").Value) descending
select c.Attribute("ID").Value).FirstOrDefault()
) + 1;
}

public static void Delete(Customer customer)
{
XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

XElement customerElement = data.Descendants("Customer").Where(c =&gt; c.Attribute("ID").Value.Equals(customer.ID.ToString())).FirstOrDefault();
if (customerElement != null)
{
customerElement.Remove();
data.Save(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));
}
}

As with the update code I’m selecting the element based on the customer ID. Once I have that element all I need to do is call the Remove method on it, then save the XDocument.

I have put all this code to use with a GridView and ObjectDataSource in the following form:
<div>
<table><tbody>
<tr>                 <th>
Forename</th>                 <td>
<asp:textbox id="txtForename" runat="server">
</asp:textbox></td>             </tr>
<tr>                 <th>
Surname</th>                 <td>
<asp:textbox id="txtSurname" runat="server">
</asp:textbox></td>             </tr>
<tr>                 <th>
DOB</th>                 <td>
<asp:textbox id="txtDOB" runat="server">
</asp:textbox></td>             </tr>
<tr>                 <th>
Location</th>                 <td>
<asp:textbox id="txtLocation" runat="server">
</asp:textbox></td>             </tr>
</tbody>         <tfoot>
<tr>                 <td colspan="2">
<asp:button id="btnAddCustomer" onclick="btnAddCustomer_Click" runat="server" text="Add Customer">
</asp:button></td>             </tr>
</tfoot>     </table>
</div>
<div>
<asp:gridview autogeneratecolumns="false" autogeneratedeletebutton="true" autogenerateeditbutton="true" datakeynames="ID" datasourceid="odsCustomers" id="gvCustomers" runat="server">
<columns>
<asp:boundfield datafield="Forename" headertext="Forename">
<asp:boundfield datafield="Surname" headertext="Surname">
<asp:boundfield datafield="DOB" headertext="DOB">
<asp:boundfield datafield="Location" headertext="Location">
</asp:boundfield></asp:boundfield></asp:boundfield></asp:boundfield></columns>
</asp:gridview>

<asp:objectdatasource dataobjecttypename="LinqToXml.Customer" deletemethod="Delete" id="odsCustomers" runat="server" selectmethod="GetCustomers" typename="LinqToXml.Data.DAL" updatemethod="Save">
</asp:objectdatasource></div>

The only code required on the web form is the code to add a new customer, as the selecting, updating and deleting is handled by the ObjectDataSource by calling the methods discussed above:

protected void btnAddCustomer_Click(object sender, EventArgs e)
{
Customer customer = new Customer()
{
Forename = txtForename.Text.Trim(),
Surname = txtSurname.Text.Trim(),
DOB = txtDOB.Text.Trim(),
Location = txtLocation.Text.Trim()
};

Data.DAL.Save(customer);

ClearForm();
gvCustomers.DataBind();
txtForename.Focus();
}

private void ClearForm()
{
txtForename.Text = string.Empty;
txtSurname.Text = string.Empty;
txtDOB.Text = string.Empty;
txtLocation.Text = string.Empty;
}

My resulting form looks like this: