Developing For .NET

Real World .NET Methods, Tricks, and Examples

Archive for January, 2008

Upgrade your C# Skills part 5 – LINQ to XML

I am working on a project that requires a configuration file that can be edited or even replaced by the user. Looking at the requirements, what I really need is a series of “records” of the same layout, similar to a database table. Naturally, given the current state of technology, an XML file is the obvious choice. So I decided that now would be a good time to investigate LINQ to XML.

Understanding LINQ to XML

First of all, unlike other LINQ topics, this one is not really query oriented. LINQ to XML (also known as XLINQ) is primarily about reading and writing XML files. Once read into program variables, you can use LINQ to Objects technologies to perform query functions.

First, the XLINQ classes are not part of the standard System.Linq namespace. Instead, you will need to include System.Xml.Linq. This namespace contains the XML classes that make XLINQ worthwhile, and we’ll review a few of these as we go along.

Second, this article will be a far cry from exhaustive on the subject: there are a ton of additional features and topics that I will not cover. Chief among the reasons for this is that I am far from an XML expert. I consider myself a typical developer where XML is concerned: my programs need to find and consume information stored in an XML format. I may even have occasion to update or write XML content. Otherwise, XML holds no particular glamor for me.

Reading an XML File

Most articles I have read on this topic begin with using XLINQ to create XML structures and files. My first task was to read an existing XML file, so that is where I will begin.

Here is the XML data I will be using for this article:

<LayoutItems Class="">
  <LayoutItem Name="FullName">
    <Row>2</Row>
    <Column>5</Column>
  </LayoutItem>
  <LayoutItem Name="Address1">
    <Row>3</Row>
    <Column>10</Column>
  </LayoutItem>
  <LayoutItem Name="Address2">
    <Row>4</Row>
    <Column>10</Column>
  </LayoutItem>
  <LayoutItem Name="City">
    <Row>5</Row>
    <Column>10</Column>
  </LayoutItem>
  <LayoutItem Name="State">
    <Row>5</Row>
    <Column>40</Column>
  </LayoutItem>
  <LayoutItem Name="Zip">
    <Row>5</Row>
    <Column>44</Column>
  </LayoutItem>
</LayoutItems>

This is a simple configuration file for a printing product I am writing. The root element LayoutItems has a Class attibute and contains a collection of child LayoutItem objects. Each LayoutItem has a Name attribute that references a Property name in the Class listed in the LayoutItems Class attribute. Each LayoutItem element then contains Row and Column elements. I’m pretty confident you can guess what these represent. This is a simple example, but no matter how complex your XML layout is, these same techniques will work.

First, we need to get an object that we can use to read and process our XML data. There are two that we can use: XDocument and XElement. If we use XDocument, we have to pull an XElement out of it to use our data, so an easier solution is to bypass the XDocument altogether and just use the XElement approach.

There are several ways to create a usable XElement object. This example uses XElement’s static Load method. In this case I am passing it the path of the XML file:

// Load XML from file
XElement xml = XElement.Load(XmlPath);

Dropping into debug after this happens shows us that the XElement object now contains all the XML from our file. All the nodes in an XElement are represented by other XElements. This nesting may look confusing at first, but it makes sense, like the Nodes of a TreeNode. Each subsequent element contains all the information for that element, including any other child elements. In our simple example there is only one sublevel of elements, but again the same techniques would work regardless of how deeply nested your data.

Now, in order to read through my XML data, I am going to loop through the Elements collection:

// Loop through Elements Collection
foreach (XElement child in xml.Elements())
{
    // Process child XElement
}

Each of these XElement objects will represent one LayoutItem section. The LayoutItem element has a Name attribute that I need to read, so I am going to use the XElement’s Attribute property:

// Read an Attribute
XAttribute name = child.Attribute("Name");

There is also an Attributes property that is a collection of all the XAttribute objects. If you had multiples to process or did not know the attribute names, this would be a simple enough option to use.

I want to point out that frequently the methods ask for an XName value. You will quickly find though that XName has no constructor. According to the documentation, wherever an XName is asked for, sending a string will perform an implicit conversion and create an XName object. I’m sorry, but this is really stupid: it creates unnecessary confusion in Intellisense and is not clear or intuitive. All that being said, now that you know, whenever you see “XName”, think “string”.

Now, since I have no further nesting to deal with, I’m ready to go ahead and read my child element data. The code is very similar to the Attribute code, except now we are using the “Element” property:

// Read an Element
XElement row = child.Element("Row");
XElement column = child.Element("Column");

Now that we have our Attributes and Elements, it’s time to actually use the values. To do this, we need to extract the values out of our XElement object. To accomplish this, you have two options. First, you can always use ToString() to get the string representation of the data and then manually convert to the desired type:

// using ToString() to extract data
string val = row.ToString();
float realVal = Convert.ToSingle(val);

Another option that will let you bypass that step is to use one of the built in cast operators to get the appropriate type directly:

// using a built in Cast operator
float realVal = (float)row;

There are built in cast operators for all the expected cast of characters like int, bool, DateTime, etc.

Creating and Writing XML

I used Visual Studio to create my XML file, but writing XML is pretty straightforward as well. Essentially, you need to create XElement objects and add other XElement objects to their Elements collection. Let’s create the above document in code.

The XElement constructor has several overloads. To just create an XElement, you can simply create a new one and pass it the name of the Element:

// Create a new XElement
XElement root = new XElement("LayoutItems");
// Add an Attribute
root.Add(new XAttribute("Class", ""));

Now, what would be intuitive would be able to access the Attributes and Elements collections and use their Add() methods to add content to them. Unfortunately, this is not possible because these are Read-only collections. XElement has an Add method of its own that accepts single content objects or a params[] construct. You can also use this method on the constructor, so let’s use the constructor method to create a few new XElements and add them to our root:

// Create and add more elements
XElement elm1 = new XElement("LayoutItem",
    new XAttribute("Name", "FullName"),
    new XElement("Row", 2),
    new XElement("Column", 5));
root.Add(elm1);

XElement elm2 = new XElement("LayoutItem",
    new XAttribute("Name", "Address1"),
    new XElement("Row", 3),
    new XElement("Column", 10));
root.Add(elm2);

XElement elm3 = new XElement("LayoutItem",
    new XAttribute("Name", "Address2"),
    new XElement("Row", 4),
    new XElement("Column", 10));
root.Add(elm3);

XElement elm4 = new XElement("LayoutItem",
    new XAttribute("Name", "City"),
    new XElement("Row", 4),
    new XElement("Column", 10));
root.Add(elm4);

XElement elm5 = new XElement("LayoutItem",
    new XAttribute("Name", "State"),
    new XElement("Row", 5),
    new XElement("Column", 40));
root.Add(elm5);

XElement elm6 = new XElement("LayoutItem",
    new XAttribute("Name", "Zip"),
    new XElement("Row", 5),
    new XElement("Column", 44));
root.Add(elm6);

Debug will now show that our root XElement object now contains all the properly formatted XML. To write it to the file system, you can use the standard StreamWriter options, or you could use the built in Save() method:

// Write file
root.Save("myFileName.xml");

In this example, I am just passing the string of the path of the file I want. There are several other overloads, but I’m confident you will be able to use them with no problem.

Conclusions

Like I said at the beginning, you didn’t see any query features here, because in this case the LINQ parts really happen in the XML processing. The Attributes and Elements collections implement IEnumerable<T>, so if you need to query them you can do so using LINQ to Objects techniques.

Personally, these new classes finally make XML an attractive solution. I finally feel like reading and processing XML can be pain free and straightforward. I know that I will be using a lot more XML in the future as a result.

3 comments

Total Training – Expression Blend Review Part 2

Well, 17 hours later I have completed my Blend Video Tutorial odyssey begun in Part 1. By the end, I was definitely feeling a little overwhelmed. Let’s face it: there is a lot to learn! Microsoft says this is the first significant shift in UI technology since the GUI was invented over 25 years ago, and I have to say they are right. Any such paradigm shift is going to cause its fair share of confusion and issues.

But let me say this here and now: it is going to all be worth it.

The Product Review

I covered most of it in the previous post, and watching another 8 hours of training only solidified my opinion: this is a good product. Gagne thoroughly knows the material and presents it in fine fashion. By the end of watching him work through samples and applications, I would at times feel like an old hat. I actually was able to grasp and understand the basics, and even learned a bit about using and navigating Blend. At the same time, I kept seeing new things and being amazed right up to the end.

I think the best thing about this product is that it wasn’t all theoretical garbage. I think we’ve all seen too many demos that don’t really show you anything. In this case, you get to actually watch him work and he does a great job of explaining exactly what he is doing and why. And if there is a downside, that is it as well: he occasionally spends too much time trying to explain C#, but like I said previously I can live with it.

I would be happy to recommend this series.

And now more on Blend

I wanted to mention a few things about Blend, XAML, and WPF that came to mind during this process.

First, there have been some grumblings in the community about the approach Microsoft took with Blend. The Microsoft theory is that Designers will use Blend to create the interfaces, and developers will use Visual Studio to provide the functionality. My guess is that most developers, yours truly included, are both designer and developer. As a result, we are a little annoyed that MS would try to keep tools from us by separating them. In other words, as I’ve heard the question asked before: “Why aren’t the Blend Tools simply part of Visual Studio?”

For a while, as both designer and developer, I have to admit I had the same questions. Now, however, I am starting to see the grand vision. First of all, there are a ton of graphical features in Blend, far more so than we have ever seen in VS. And some of these tools really are graphics designer oriented. In fact, graphics are the entire point of Blend, XAML, and WPF. Personally, I am not a graphics guy. I create websites, but rarely the graphics that go on them. In fact, I have often though that was the next step for me if I wanted to increase my Web skills.

But I’m not sure I have the patience or even really the desire to become a graphics guy. The good news is that I think the average developer can create some really cool stuff courtesy of Blend, without having to become a true graphic artist. What we don’t need is to have the vast amount of features and functions for Blend bloating up VS. I think MS has done the right thing by separating the two, and at the same time they have also done a great job of integrating the two products. You can, and I’m sure will, use them side by side, simultaneously working on the same projects and files.

The effects you can produce are nothing short of fantastic. Of course, you can still produce some really bad looking applications: “developer art” as Gagne once refers to it. But with a little effort and training, your apps can get a real boost. Also, because of the vector graphic nature of XAML and WPF, the design possibilities are virtually unlimited.

And now for the best news of all. I have seen several demos of XAML and WPF before, a couple of them even used Blend, but in each one the presenter eventually resorted to editing XAML code manually. This always seemed a kludge and a signal that this stuff was not ready for prime time. Well, I guess now it is: not once in the entire 17 hours of video did I see Gagne manually change or edit XAML code. He got all his results actually using Blend. Now it’s my turn, and I can’t wait!

Oh… one more quick note: I had written previously about my preference for Xara Xtreme as a graphics tool. That may still be true, but I think next in the series for me will be Expression Design. Why? Because you can export the graphics as XAML files and layers, which makes them completely consumable in Blend and WPF. Folks, this stuff is seriously cool!

1 comment

Total Training – Expression Blend Review Part 1

This post is the first in a new category called “Product Reviews”. When I can, I will post reviews like this on the products I buy and use.

I mentioned previously that I purchased and ordered Total Training’s Expression Bundle. The package arrived with 6 DVD’s containing over 40 hours of Video Training. Since I am most interested in WPF, I began with the 2 DVD set for Expression Blend, each with 8.5 hours of training videos. I still have over 10 hours to go in the Blend series, but here are my first impressions.

The Good

I was impressed right away: the instructor for the Blend series is Dante Gagne. According to his introduction, Dante worked in development and testing on the Blend project and later became the instructor to the Microsoft Evangelists for Blend. In other words, he has serious credentials for training others how to use Blend.

The videos are pretty slick. There is good production value and the lessons follow a well laid out script. The supporting examples are on task and appropriate with little superfluous content. It is obvious that Dante knows this product, and the videos are replete with valuable tidbits such as Keyboard Shortcuts, alt-Mouse clicks, and other such goodies. Unfortunately, some of these go by so fast, and there are so many of them, that I know I won’t remember half of them when I start actually using Blend.

The DVDs came complete with Code Samples and Projects. These are laid out well in a folder structure that matches the lesson plan.

The Bad

I occasionally got bored while Dante covered some basics, but those periods are blissfully short and necessary given the diverse target audience. This is especially true later when he begins to include a little code behind and has to explain some C# concepts. As a C# developer myself, I would disagree with the way he characterizes some of the elements, but I can let it slide since according to Microsoft the Blend audience are Designers and not Developers.

The videos are broken up into three parts: Parts, Lessons, and Topics. The Topics range from 30 seconds to a few minutes in length. This can get annoying, because it forces a short break in between each Topic while the program loads the next one. The program is a proprietary Total Training viewer which must be installed one time before you can view any of the videos. I honestly do not see the value add for the end user: I’m sure the program gives TT more control over the presentation, such as jumping from one lesson to the next, but most likely its primary function is to ensure that the videos can not be viewed by those who have not purchased a Total Training package.

The Ugly

Unfortunately, this program is the worst part of the deal. If I begin the tutorial and do nothing else, the program works fine. The problem occurs when I need to do something else. I can pause the video and restart it, but as soon as I activate any other Window, the Total Training program no longer functions. If I activate another window while the video is running, the sound will continue to function but the video freezes and will not recover.

Once I return to the TT program and click on anything, I receive the traditional “(Not Responding)” message and the only recourse is to kill the program and start over. I can locate and start from the last lesson I was on, but this is a really bad problem, especially considering the length on these DVDs. I need to be able to pause the application and do other things (at least my boss seems to think so!) I had really intended on writing this review as I went through the material, which would have allowed me to be much more specific. Obviously, this issue makes that essentially impossible.

I will report this problem to Total Training, so it looks like we’ll have a chance to review their customer support as well. The training videos themselves are such a good product, I hate to see them brought down by something so trivial. I’ll keep you all informed of the situation. In the meantime, I will continue to struggle though.

UPDATE:

I went to the Total Training website and found a section on “Windows Vista FAQs” under Tech Support.  There, I found an entry that I used to solve the problem.  The entry was not correct, but it gave enough clues to solve the issue, which appears to be specific to Vista.

1)  The FAQ says to change “Launchpad.exe” on the DVD.  I could not find that file, and the DVD would not be writable anyway, so that did not make a lot of sense.

2) Instead, I went to the install location, in my case this is “C:\Program Files\Total Training” and there I found another folder called “TT Expression Blend Ess”.  In that folder, I changed the properties on TEBES.exe according to the link above, setting it to run in Windows XP Service Pack 2 compatibility mode.

After doing that, I can now pause and restart the training with no problem.  I anticipate doing this with each Product group.

So my review for their Tech Support will be short: I was able to quickly locate, diagnose, and solve my issue based on the information on their website.

1 comment

I hate being sick…

I caught a bug that has been terrorizing the office and I’ve been out sick since last Wednesday.  I got back in today and found my DVD copy of Total Training for Microsoft Expression Studio waiting my return.  Hopefully I’ll begin going through the training this week, and naturally I’ll give you all a review of the materials and products.

Also, I’ve been working on a Printing Framework, so I plan on writing a series of articles on Printing.

Finally, I’ll be speaking next week at RVNUG on the new .NET 3.5 C# features.  I’ll cover most of the material from the “Updgrade your C# Skills” series, so if you are there be sure to say “Howdy!”

No comments

Sun agrees to buy MySQL

OK, so I know this is not a .NET specific topic, but I thought this was important enough to share.  According to SitePoint.com, one of my favorite sites and publishers, Sun is buying MySQL for $1 Billion.  MySQL has been instrumental in the growth of Open Source, the acceptance of PHP, and the explosion of Internet interests such as blogs.  Without a stable, reliable, easy to use, free database, none of these things would have been nearly as successful or prolific as they have been.  For many, this represents a sell out by one of the corner stones of the Open Source movement.

Fortunately, according to the post above, Sun has a good track record of acquiring but not destroying Open Source technologies:

But there is other evidence of Sun understanding the value of keeping software open source and free: projects like OpenOffice.org and NetBeans have healthy communities and promising road maps. In fact, if you examine Sun’s current offerings to the corporate world, the only key component missing from the portfolio (and one that competitors such as Oracle, IBM, and Microsoft already offer) is a database. MySQL, with over 10 million installations worldwide (including high-traffic sites such as Google and Facebook) is a natural fit.

I have written here before about one of my first projects, a wrapper system for accessing multiple ADO.NET data sources.  MySQL was one of the initial databases that project supported (and still does today).  We use MySQL a lot for Internet applcations, so I will be watching this development with some interest.

2 comments

Next Page »