Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Outlook Type Address Book in C#, LINQ, XML with Menu and ToolBar

4.70/5 (8 votes)
28 Aug 2009CPOL4 min read 41.6K   1.6K  
Outlook type Address Book in C#, LINQ, XML with Menu and ToolBar

Introduction

This is a sample project to create an Outlook type address book with LINQ and XML. It also shows how to use menu and toolbars in your Windows application.

Background

LINQ (Language Integrated Query) is a Microsoft .NET Framework component that adds native data querying capabilities to the .NET languages. It allows you to query collections like arraylist, List, etc. LINQ to XML is a new way to construct, write and read XML data in the .NET language of the developers’ choice. This new API simplifies working with XML data without having to resort to using additional language syntax like XPath or XSLT. LINQ to XML is not a replacement for any of the current DOMs or XML class libraries; LINQ to XML in many cases overlaps their functionality and aims to provide a superior developer experience, but existing code will continue to work. One aspect of LINQ to XML is that it supports writing Query Expressions and can be combined with any of the other LINQ technologies to create or use XML data as a source or destination format.

Using the Code

The Address Book is created in C# with XML as a database to store the contacts. Addition, deletion and updation of the records to this XML file is done with LINQ.

Most of the coding is easy to understand as you go through the sample project. I will explain how I use LINQ to work with my XML file.

Make sure you have a reference to System.LINQ and System.XML.LINQ in order to work with LINQ to XML.

If you go through the static class XMLParse, you will see that all the coding related to LINQ is done here. Let me explain how it works.

Create a new XDocument class object like this:

C#
XDocument xmlDoc = XDocument.Load(XMLFilePath);

This will represent your entire XML in the memory. So now we can query this xmlDoc to retrieve the records like this:

C#
var addresses = from Address in xmlDoc.Descendants("Address")
select new {
    FirstName = Address.Element("FirstName").Value,
        LastName = Address.Element("LastName").Value,
        Email = Address.Element("Email").Value,
        Address1 = Address.Element("Address1").Value,
        Address2 = Address.Element("Address2").Value,
        City = Address.Element("City").Value,
        Country = Address.Element("Country").Value,
        Zip = Address.Element("Zip").Value,
        Phone1 = Address.Element("Phone1").Value,
        Phone2 = Address.Element("Phone2").Value,
        State = Address.Element("State").Value,
};

Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type. Here our var addresses will have the following properties like FirstName, LastName....State. Their values are filled from the elements of XML. A point to note here is that these var addresses will act like a collection which will have a collection of objects and each object will have those properties. So now if you want to fill your List with objects of the contacts class, this is how you do it:

C#
foreach (var address in addresses)
{
    Contacts contact = new Contacts();
    contact.FName = address.FirstName;
    contact.LName = address.LastName;
    contact.Email = address.Email;
    contact.Address1 = address.Address1;
    contact.Address2 = address.Address2;
    contact.City = address.City;
    contact.State = address.State;
    contact.Country = address.Country;
    contact.Phone1 = address.Phone1;
    contact.Phone2 = address.Phone2;

    ContactList.Add(contact);
}

Add Contact

Look at the AddContact function of the XMLParse class. To add a new contact, create a new XElement and add it to the Root node of your XDocument which is xmlDoc. The first parameter is the main node and from the second parameters, it will be XElements which will go inside this main node.

C#
xmlDoc.Root.Add(
                new XElement("Address",
                new XElement("FirstName", contact.FName),
                new XElement("LastName", contact.LName),
                new XElement("Email", contact.Email),
                new XElement("Address1", contact.Address1),
                new XElement("Address2", contact.Address2),
                new XElement("City", contact.City),
                new XElement("Country", contact.Country),
                new XElement("Zip", contact.Zip),
                new XElement("Phone1", contact.Phone1),
                new XElement("Phone2", contact.Phone2),
                new XElement("State", contact.State)
                ));

Once you have added the new XElement, it is added to the XML document in the memory. We need to update the main XML file on the disk. So:

C#
xmlDoc.Save(XMLFilePath);

Update Contact

I have designed with the email address to be the primary key. So to update, we will match the email address and then update that respective XElement. So let's say, I have the email address which needs to be updated. Go ahead and get the XElement from your in memory xmlDoc:

C#
XElement element = xmlDoc.Root.Elements("Address").Where(r => (
    string)r.Element("Email") == contact.Email).FirstOrDefault();  

This will return the element where the email address matched. FirstOrDefault() will return the first occurrence where it matched or the default value.

Use the SetElementValue function of XElement class to update the value like this:

C#
if (element != null)
{                                  
    element.SetElementValue("FirstName", contact.FName);
    element.SetElementValue("LastName", contact.LName);
    element.SetElementValue("Email", contact.Email);
    element.SetElementValue("Address1", contact.Address1);
    element.SetElementValue("Address2", contact.Address2);
    element.SetElementValue("City", contact.City);
    element.SetElementValue("Country", contact.Country);
    element.SetElementValue("Zip", contact.Zip);
    element.SetElementValue("Phone1", contact.Phone1);
    element.SetElementValue("Phone2", contact.Phone2);
    element.SetElementValue("State", contact.State);
    xmlDoc.Save(XMLFilePath);
}

Delete Contact

Delete will work in the same way as update works. But in this case, we will query the xmlDoc to get the element and then use the remove function to remove the element.

C#
XElement element = xmlDoc.Root.Elements("Address").Where(r => (string)r.Element(
    "Email") == emailAddress).FirstOrDefault();        
if(element!=null)           
element.Remove();

Points of Interest

LINQ is a really cool way of working with XML and SQL. It makes a developer's life quite easy. Also this address book sample is a complete independent sample. You can create a DLL of this project and can use it with any of your existing applications.

History

  • 28th August, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)