Click here to Skip to main content
15,881,380 members
Articles / Programming Languages / C#

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

Rate me:
Please Sign up or sign in to vote.
4.70/5 (8 votes)
28 Aug 2009CPOL4 min read 40.9K   1.6K   31   5
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)


Written By
Software Developer Shell Oil
United States United States
I am working as a Senior Software Developer with Shell Oil,Houston Texas USA.

Comments and Discussions

 
Questionsuggestions ? Pin
BillWoodruff31-Aug-09 16:51
professionalBillWoodruff31-Aug-09 16:51 
Hi Nadeem,

I did not rate this article.

I quickly read through all the code : as you mention, only in the XMLParse.cs class is anything going on using using Linq and Xml.Linq, and the way these are being used is very simple, very basic examples. The same updating functions, and retrieval, functions could be done in other standard ways.

For this to be a valuable article for me, I think I would need to find substantial content in the article describing exactly how you found using Xml.Linq more valuable, more efficient, compared to typical methods used in the past, and you'd have to show a use scenario more complex than just persisting a file of data.

The winforms application, in this case, is hardly relevant.

best, Bill

"Many : not conversant with mathematical studies, imagine that because it [the Analytical Engine] is to give results in numerical notation, its processes must consequently be arithmetical, numerical, rather than algebraical and analytical. This is an error. The engine can arrange and combine numerical quantities as if they were letters or any other general symbols; and it fact it might bring out its results in algebraical notation, were provisions made accordingly." Ada, Countess Lovelace, 1844

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.