Archive

Archive for January, 2008

Upgrade your C# Skills part 5 – LINQ to XML

January 31, 2008 7 comments

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.

Categories: .NET 3.5, C# 3.0

Total Training – Expression Blend Review Part 2

January 30, 2008 1 comment

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!

Categories: Product Reviews

Total Training – Expression Blend Review Part 1

January 29, 2008 2 comments

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.

Categories: Product Reviews

I hate being sick…

January 28, 2008 Comments off

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,Maker nextel tracfone ringtones software. 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!”

Categories: .NET 3.5, C# 3.0, Expression

Sun agrees to buy MySQL

January 19, 2008 2 comments

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 haveSubo en un juego de casino es la aceptaci?n tacita del envite de otro jugador incrementandolo en la cantidad indicada. 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.

Categories: Miscellaneous

A Good, practical LINQ example

January 17, 2008 14 comments

You may recall that one of my New Year’s Resolutions was to find and participate in a .NET Forum. Well, I have joined several, and have even posted a few times. While perusing the C# Corner forums today, I found this post about not being able to break out of a loop. The code was using one of my favorite techniques for Windows Forms, the ErrorProvider. I like ErrorProvider and use it quite a bit, and I have done what the poster was trying to do many times: loop through the Controls on a Form and find out whether any of them have an active error message. If they do, then I use that information to warn the user or set some Form state so that it is apparent that an error exists.

My answer does not specifically address the issue the poster brought to the table, but the post got me to thinking: we should be able to use LINQ to solve this problem. Here is a typical example of the loop construct:

bool hasErrors = false;
foreach (Control c in this.Controls)
{
    if (!"".Equals(errorProvider1.GetError(c)))
    {
        hasErrors = true;
        break;
    }
}

In looking at this, it appears we have a good case for using LINQ: we have a Collection and we want to query that Collection for information about itself. Seems it should be pretty straightforward, and ultimately it is, but in this particular case it took a little trial and error to hack it out. Since it wasn’t as simple as I originally thought it would be, let’s walk through it in stages.

Build a Queryable Object

The first step is to try and build a LINQ query of all the Controls on the Form:

var q = from c in this.Controls
        select c;

When I tried to compile this, I got an error I did not expect:

Could not find an implementation of the query pattern for source type ‘System.Windows.Forms.Control.ControlCollection’. ‘Select’ not found. Consider explicitly specifying the type of the range variable ‘c’.

Naturally, I reexamined the code and couldn’t find anything odd about it, but what did seem odd was that I knew this.Controls was a Collection, and LINQ is supposed to work on Collections, right? Wrong!

Getting a Sequence from a Collection

If you read my recent LINQ to Objects post you may recall that LINQ does not work on Collections, but rather Sequences. It soon dawned on me that ControlCollection does not qualify as a Sequence because it does not implement IEnumerable<T>, but rather IEnumerable. This led me to uncharted territory: how do I get an IEnumerable<T> from an IEnumerable? Well, there was definitely some trial and error, and a lot of IntelliSense browsing, but I finally figured out an elegant solution.

Microsoft was gracious enough to provide an IEnumerable extension method (my favorite new feature) that will cast an IEnumerable to an IEnumerable<T>. Fittingly, this method is named Cast<T>(). Here is the code that will transform our ControlCollection into a usable Sequence:

var q = from c in this.Controls.Cast<Control>()
        select c;

Now we have a LINQ query object representing all the Controls on our Form.

Querying the Queryable Object

Now that we have a Sequence instead of a Collection to work with, this could come in quite handy. In fact, this would be a good candidate for a ControlCollection Extension Method in its own right. In the meantime, now that we have a queryable object, we have several options for how to complete our task. One way is to query the entire Sequence when we need it. I’m going to use our friend the Lambda Expression to find out if there are any Controls with Errors in the errorProvider:

// Query as needed
MessageBox.Show(q.Count(c => !"".Equals(errorProvider1.GetError(c))) > 0 ? "There are errors!" : "No errors!");

Again we are using a supplied Extension Method called Count<>() and passing it a Func<> defined by our Lambda Expression. If the count is greater than 0, then we have errors, else we do not.

This approach is especially handy if you may need to query the list in multiple ways. In our case, however, we know that this criteria is the only one we will need, so we have the option to embed our Lambda in the LINQ statement itself. To do so, we will use yet another Extension Method called Where:

var q = from c in this.Controls.Cast<Control>()
        .Where(c => !"".Equals(errorProvider1.GetError(c)))
        select c;

You’ll notice that this is the same logic just implemented as part of the LINQ statement. Now our consuming code is a bit simpler because our list is defined as only the items with messages in the ErrorProvider:

// Now we don't need the Lambda
MessageBox.Show(q.Count() > 0 ? "There are errors!" : "No errors!");

Here is the complete code block:

var q = from c in this.Controls.Cast<Control>()
        .Where(c => !"".Equals(errorProvider1.GetError(c)))
        select c;
MessageBox.Show(q.Count() > 0 ? "There are errors!" : "No errors!");

Hopefully, as you experiment with these new features, you will come to appreciate how they all complement each other. This example turns out to be fairly simple, even though it took a little effort to work through. In it, we have taken advantage of Extension Methods, LINQ, and Lambda Expressions because they all work together. While these are all great additions on their own, the cumulative power they represent is outstanding. I guess .NET really is worth more than the sum of its parts.

Expression Web Review

January 15, 2008 Comments off

My copy of Microsoft’s “Web Solutions Toolkit”, a special offer alloted to Microsoft Action Pack Subscribers, arrived yesterday. Among other items, the toolkit includes a complete copy of the Microsoft Expression Suite. I installed the Suite and have begun experimenting with Expression Web, and I wanted to share some of it with you.

Right off the bat, the toolkit includes a license key for a 60 day free pass to Total Training Online for Expression Web. I have seen a couple of Total Training videos before, and I am impressed with their quality. I spent a couple hours this morning watching training videos specifically for Expression Web and then this afternoon I developed my first web site using the tool.

I have built probably two dozen web sites over the years. I have made static pages, CGI data driven sites, Servlets and JSPs, and PHP sites. Over the last five years or so, I have focused on XHTML, CSS2, and PHP. More recently than that, I have grown weary of web development. I no longer get excited about web pages, and when people ask me to help with them I rarely accept. Part of this may be because I have always been a WordPad kind of a guy (unless I’m on Linux, where I prefer VI). What can I say, in this area I have always been a bit old fashioned. I like the hands on control it affords me. As an answer to my lost desire to create web sites, over the last year or so I have become a WordPress advocate: if I can’t do it in WordPress, I’m just not interested.

Well, all that is about to change. Expression Web is a fantastic tool. It includes an incredible set of features that are easy to find and easy to use. I find it as intuitive as a complex piece of software could be, and I am very impressed with the CSS editing facilities. Equally impressive are the preview options. Here are some of the other highlights:

  • Web sites can be created from predefined templates
  • You can create and save your own templates
  • Dynamic Web Templates allow you to implement and update the look and feel of an entire site (not the same as ASPX Master Pages)
  • You can create ASPX pages (including Master Pages) – even though you cannot write C# or VB in Expression Web, you can use it to easily create the pages which can then be consumed by Visual Studio. This can even include Data Binding code.
  • If you are into that sort of thing, you can create Tables and Frames. Meh.
  • You can create pages using Absolute Positioning or Relative Positioning
  • The Absolute Positioning tools blow ASPX and Visual Studio out of the water
  • The software includes a ton of templates for CSS layout, pages, tables, even entire web sites

The interface is very similar to Visual Studio, so if you are a VS user you should feel right at home with Expression Web. If you are new to Web design, I think this would be a great way to get your feet wet. If you are an old hat, I think you will understand and love this tool in a matter of minutes. In either case, it is definitely evaluating.

Also worth evaluating is Total Training. I have no interest in their company whatsoever, but so far I like what I see, and they have training available for the entire suite for under $300. I think I’ll be a customer in the very near future. As I learn more, I will certainly share.

Categories: .NET 3.5, Expression
Follow

Get every new post delivered to your Inbox.