jQuery: creating new tags

We’ve seen that we can select existing elements on a web page in many ways using the $(selectorsyntax, where ‘selector’ can take on any of the many forms we’ve seen in earlier posts. The $() syntax can also be used to create new HTML which can then be inserted into your document.

To do this, simply put the desired HTML (enclosed in quotes) directly as the argument. Thus $(‘<input type=text/>’) creates a new text input box.

Merely creating a new object does not, however, insert it into the document. To do that, you need to use a method such as appendTo(). Thus  $(‘<input type=text/>’).appendTo(‘body’) will add the text box to the end of the body, so that it appears at the bottom of the page.

The easiest way of trying this feature out is to load a page (such as the one we’ve been using for examples up to now) that uses jQuery into a browser such as Chrome that has a console, and then typing some commands into the console. The results should be instantly visible on the page.

That’s about all there is to say about the single-argument method of creating HTML. There is, though, another version, in which a second argument can be passed. This second argument allows attributes to be specified.

It’s true that we could just include all the attributes in the raw HTML in the first argument, but it’s sometimes cleaner and easier to read if we can lay out the attributes more explicitly.

For example, we could create a new text input as follows:

$('<input />',
  {
    type: 'text',
    title: 'A test text box',
    click: function () {
      alert($(this).attr('title'));
    },
    css: {
      backgroundColor: 'peachpuff',
      border: '2px dotted red'
    }
  }).appendTo('body');

We’ve moved the ‘type’ attribute to the second argument, and added a ‘title’ (which is displayed as a tooltip when the mouse hovers over the text box). We’ve also added an event handler for a mouse click, which just displays an alert box containing the title. (It’s probably more conventional to add the event handler using a method, but putting it in the attribute list is perfectly valid.)

We’ve also added a couple of style properties in the css attribute. The css attribute is a bit odd in that it gets translated to a ‘style’ attribute in the HTML, and some of the attribute names get changed. For example, the css ‘backgroundColor’ is changed to ‘background-color’ in the style. You can, if you like, specify the ‘style’ attribute explicitly in the jQuery, but you’ll have to use the style names instead of the css names, and put the whole set of styles into a single string. The above example would be written:

$('<input />',
  {
    type: 'text',
    title: 'A test text box',
    click: function () {
      alert($(this).attr('title'));
    },
    style: 
      'background-color: peachpuff; border: 2px dotted red' 
 }).appendTo('body');
Advertisements

jQuery: special selectors

We’ve seen how to select document elements based on their tags, ids, classes and attributes. jQuery also provides a number of specialized selectors and filters.

We’ll use the same HTML code as before for our examples. Here it is:

<body>
  <h2>jQuery Selectors</h2>
  <table>
    <tr>
      <th colspan="2">Comic Summary</th>
    </tr>
    <tr class="headerRow">
      <th id="comicHeader" class="header cell">Comic</th>
      <th id="numberHeader" class="header cell">Number</th>
    </tr>
    <tr>
      <td class="cell">Thor</td>
      <td class="cell">34</td>
    </tr>
    <tr>
      <td class="cell">Superman</td>
      <td class="cell">158</td>
    </tr>
    <tr>
      <td colspan="2">
        Which is best?<br />
        <label> <input type="radio" name="dcMarvel" /> DC</label>
        <label> <input type="radio" name="dcMarvel" /> Marvel</label>
      </td>
    </tr>
    <tr>
      <td colspan="2">
      What are your favourites?
        <ul>
          <li><label><input type="checkbox" />Batman</label></li>
          <li><label><input type="checkbox" />Superboy</label></li>
          <li><label><input type="checkbox" />Fantastic Four</label></li>
          <li><input type="checkbox" />Iron Man</li>
          <li><input type="checkbox" />Incredible Hulk</li>
          <li><input type="checkbox" />Green Lantern</li>
        </ul>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <input type="text" id="jqtest" /></td>
    </tr>
  </table>
</body>

Selecting by position

There are several ways of selecting elements based on their position in a list. The filters :first and :last (all filters begin with a colon (:)) select the first and last elements in the selected context, respectively. For example, if we wrote $(‘li:first’) we would select the first li element on the page (which is the Batman checkbox). Similarly, $(‘li:last’) selects Green Lantern.

The :first and :last filters ignore the depth of nesting of elements and just pick out the absolute first and last matching elements. Thus $(‘label:first’) gives the DC radio button and $(‘label:last’) gives the Fantastic Four checkbox.

If we omit a selector before the filter, jQuery uses the entire page as the context. Thus $(‘:first’) selects the <html> tag which encloses the whole page, and $(‘:last’) selects the text input tag at the bottom.

The :first-child filter selects the first element in the context that is a child of another element. $(‘label:first-child’) gives the first three labels in the checkbox list because each of these labels is the first child of a li tag. Note that it does not include the DC radio button since, although this button is the first label child of the td tag, it’s not the first child: the br tag has that honour. If we delete the br tag, then the DC button is included; the text ‘Which is best?’ within the td does not count as a child since it just part of the td tag.

As you might expect, $(‘label:last-child’) selects labels that are last children of another node. In this case we get the first three checkbox labels (since they are the only children, they are both first and last children) and the Marvel radio button.

$(‘label:only-child’) selects labels that are the sole child of another node; here that means the first three checkbox labels.

There are also filters :even and :odd which select even and odd elements from the context, using a zero-based index. Thus $(‘li:even’) selects Batman, Fantastic Four and Incredible Hulk and $(‘li:odd’) selects Superboy, Iron Man and Green Lantern.

We have :eq(n), :gt(n), and :lt(n) for finding elements that are at index location n, or greater than or less than n. Again, n is zero-based. Thus $(‘li:gt(2)’) selects Fantastic Four, Incredible Hulk and Green Lantern.

Finally, there is the :nth-child(n) selector, which is a bit unusual, in that its index argument starts at 1 rather than 0. (This is for compatibility with CSS, but if you’re working with jQuery it can be a bit of a pain, since all the other index-based selectors start with a 0 index.) $(‘li:nth-child(2)’) gives Superboy.

There are a couple of other versions of :nth-child(). One takes an argument of ‘even’ or ‘odd’ which returns the even or odd elements in the list, except of course because the list now starts with 1, these give complementary results to using just ‘even’ or ‘odd’ on their own. That is $(‘li:nth-child(odd)’)  gives the same result as $(‘li:even’) and vice versa.

The final form of :nth-child() takes a simple formula as its argument. We can write :nth-child(Xn+Y where  and Y are integers. This will return every Xth element, starting with element Y. Thus $(‘li:nth-child(3n+2)’) returns every 3rd element starting with element 2, giving Superboy and Incredible Hulk.

Custom filters

There are quite a few filters that do their selection based on the type or state of element you’re interested in. Filters that select specific types of element are :button, :checkbox, :file (equivalent to ‘input [type=file]’), :header (selects <h1>…<h6>), :image (same as ‘input [type=image]’), :input (any form input element), :password, :radio, :submit (same as ‘input [type=submit]’), :reset and :text (same as ‘input [type=text]’). These should all be fairly self-explanatory, but give them a try using the HTML above and the header block given earlier, and use the Console in Chrome or Firefox to see what you get.

Somewhat more interesting are the filters that act on the state of an element. The :checked filter selects radio buttons or checkboxes that are checked.

This seems a good place to introduce the tricky :not() filter. As you can guess, it returns the inverse of whatever selector is passed to it as its argument, but you have to be a bit careful. For example, you might think that since :checked gives all radio buttons and checkboxes that checked, :not(:checked) should give you all radio buttons and checkboxes that are not checked. In fact, what it does give you is all elements that are not checked, which means every element on the page (including non-radio buttons and non-checkboxes) except radio buttons and checkboxes that are checked.

If you want just the non-checked checkboxes, you can write $(‘:checkbox:not(:checked)’), since that restricts the context to just checkboxes before applying the :not filter. If for some reason you actually do want both unchecked radio buttons and checkboxes, you can write $(‘:radio:not(:checked), :checkbox:not(:checked)’) being careful not to leave out the comma in the middle.

The :contains() filter can also trap you. Its argument is some text, and it returns all elements that contain that text. The trap lies in the fact that if any element within the context is an ancestor of the element that contains the text, that element also gets included in the results. For example, if we wrote $(‘:contains(best)’), then the td element containing this text would be selected, but so would the html, body, table, tbody and tr elements that are that td’s ancestors. To get just the td element, we would have to write $(‘td:contains(best)’).

If we want to select tag types that have another tag type as their ancestor, we have already seen that we write, for example $(‘tr li’) to find li elements that are children of tr elements. The :has() filter can do the inverse; it finds elements that have a particular type of element as a descendent.

$(‘tr:has(li)’) returns the tr element containing the checkbox list. Again, note that the child element can be at any depth below the parent.

The remaining filters are all fairly obvious. They are :disabled, :enabled, :hidden, :visible, :selected and :parent. The :parent filter returns elements that are parents, not the parents of elements. If you want to find the parents of a set of elements, you need to use the parent() function rather than a filter. Thus $(‘li’).parent() finds the ul element that is the parent of all the li tags.

jQuery selections: id, class and attributes

In the last post, we saw how to select page elements by searching for tag names. Sometimes, we’d like to select elements based on other criteria. There are several ways of labelling or marking tags.

For the purposes of an example, we’ll modify the body of the page given in the previous post, so it now becomes:

<body>
  <h2>jQuery Selectors</h2>
  <table>
    <tr>
      <th colspan="2">Comic Summary</th>
    </tr>
    <tr class="headerRow">
      <th id="comicHeader" class="header cell">Comic</th>
      <th id="numberHeader" class="header cell">Number</th>
    </tr>
    <tr>
      <td class="cell">Thor</td>
      <td class="cell">34</td>
    </tr>
    <tr>
      <td class="cell">Superman</td>
      <td class="cell">158</td>
    </tr>
    <tr>
      <td colspan="2">
        Which is best?<br />
        <label> <input type="radio" name="dcMarvel" /> DC</label>
        <label> <input type="radio" name="dcMarvel" /> Marvel</label>
      </td>
    </tr>
    <tr>
      <td colspan="2">
      What are your favourites?
        <ul>
          <li><label><input type="checkbox" />Batman</label></li>
          <li><label><input type="checkbox" />Superboy</label></li>
          <li><label><input type="checkbox" />Fantastic Four</label></li>
          <li><input type="checkbox" />Iron Man</li>
          <li><input type="checkbox" />Incredible Hulk</li>
          <li><input type="checkbox" />Green Lantern</li>
        </ul>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <input type="text" id="jqtest" /></td>
    </tr>
  </table>
</body>

First, a tag may be given an id attribute. The HTML standard specifies that no two visible page elements may have the same id. The key word here is ‘visible’; you can define several page elements with the same id, so long as only one of them (or none of them) is visible at any given time. In the example above, we’d added an id to each of the th tags in the table.

Secondly, most page elements can be assigned a class to which they belong. The name ‘class’ is a bit misleading if you’re familiar with object oriented programming, since an HTML class doesn’t have many of the properties of a true OOP class. In HTML, a class is really little more than a label which can be used to identify groups of tags on a page. In the above HTML, we’ve assigned all the td elements to have the class ‘cell’. Unlike the id, the class of a tag need not be unique; in fact, it usually won’t be, since the idea is normally to identify a set of tags that have a common property.

A tag can belong to more than one class. In the above code, the th tags are members of both the ‘header’ and ‘cell’ classes. To define multiple classes, we list the class names separated by whitespace. Both the id and class can be any valid string.

Finally, many tags have various attributes. Although these attributes are usually used to specify some properties of the tag, they can also be used as identification. Actually, both the id and the class are attributes, but there are many others for some tags. In the above example, the first th tag has a ‘colspan’ attribute, and the radio and checkbox input tags have ‘type’ attributes (the radio buttons also have a ‘name’ attribute).

One of the most common uses of these ways of labelling tags is in specifying CSS rules, but we can also use them in jQuery selectors to pick out groups of elements on which we can act. Using the above page as an example (you can use the same head as the last section if you want to try this a live browser), we can see a few examples.

Searching using the id

To use an id, prefix the the id name with a #. For example, the expression $(‘#comicHeader’) will find the th tag with that id. Note that although ids must be unique amongst visible elements, it is possible that some currently hidden tags may have the same id, and this expression will find all tags that have that id, so you may need to filter the results to be sure of getting the one you want.

If you want to restrict the search to tags of a certain name, simply prefix the id name with the tag name. Thus $(‘th#comicHeader’) will find all th tags with an id of comicHeader (which happens to give the same result as the earlier example in this case).

It’s important to note that there is no whitespace between the th and the #. If you did put a blank between them, you would then be searching for descendents of a th node that had that id, which in this case would return an empty list. If you tried $(‘tr #comicHeader’), though, you’d then get the comicHeader node again, since it’s in a node which is a descendent of a tr node.

You can search for several ids by separating them with commas. Thus $(‘#comicHeader, #numberHeader’) finds both th nodes with ids.

Searching using the class

Using the class as a search term is pretty much the same as using the id except you prefix the class name with a period (.) instead of #. Thus $(‘.cell’) finds all tags with a class of ‘cell’.

Somewhat counter-intuitively, although you can define a tag that belongs to two classes by listing the class names separated by whitespace, if you try finding all tags that belong to both of two classes in the same way, you are doomed to fail. For example, the query $(‘.header .cell’) returns an empty list. What this query is really asking for is a list of elements with a class of ‘cell’ that are descendents of a tag with class ‘header’. Thus if we tried $(‘.headerRow .cell’) we’d then get the two th tags with a class of ‘cell’.

If you do want a list of tags that belong to both of two different classes, you have to leave out the whitespace. Thus $(‘header.cell’) will give you the two th tags again.

You can combine ids and classes in the same search. Thus $(‘#comicHeader.header.cell’) looks for tags that have an id of comicHeader and classes of both ‘header’ and ‘cell’.

Searching using attributes

Finally, you can use any attribute as a search term. The syntax for this encloses the attribute and its value in square brackets. For example, to find all checkboxes, we can use $([type=checkbox]). We’ve left the quotes off ‘checkbox’, but in fact it doesn’t seem to matter whether you use them or not; thus $([type=”checkbox”]) also works.

You can also search for tags that merely have a given attribute, regardless of what value that attribute has. For example, we can get a list of all tags that have ids by writing $([id]). The notation above for searching on id or class isn’t quite just a shorthand for using the id and class attributes though. The class has its own logic that allows things like multiple class definitions and searches, as we saw above. If we tried something like $([class=header]) we’d get an empty result. The attribute search attempts to match the exact string to the attribute, and there is no tag with just ‘header’ as its class, so the search fails.

jQuery: simple selections

Although JavaScript is very handy for client-side manipulation of web pages, it suffers from at least two serious drawbacks. First, it can take a lot of code to do relatively simple things (like finding a particular element within a web page). Second, different browsers (particularly Internet Explorer) often require different code to do the same thing, so writing a web page that will always behave the same in every browser can be a major headache.

jQuery solves many of these problems. It is a JavaScript API which defines a large number of functions that both reduces the amount of code needed and eliminates many of the cross-browser problems.

At the core of jQuery (as you might guess from its name) is its ability to search the web document in a myriad of ways. (It can, of course, do a lot of other things, but more on that later.) We’ll have a look at some of these search techniques here.

First, we need to draw an important distinction between the two ways a jQuery function can return its result. Most functions return a wrapped set, which is a set of page elements contained within a JavaScript data structure. It’s a set, since there are no duplicated elements within it, even if the search string could match the same element in more than one way. Some jQuery functions will return bare elements, but we won’t be concerned with any of those in this post.

Second, most jQuery functions are called from a wrapped set, do something to that set, and then return another wrapped set. Sometimes, the second set is the same as the first one (although with some modifications to its elements), but sometimes (as with a filter) the second set is a different set than the original, as it may contain different, or more or fewer, elements. Again, we won’t be worried about this much here, since we’re going to consider mostly just a single function that searches the page for specific elements. What we do with those elements is the subject of future posts.

The format for a query in jQuery is $(<query string>), where <query string> is a string that tells the function what to look for. If you know how to use cascading style sheets (CSS), you’ll be happy to hear that most of the CSS selector strings also apply in jQuery selectors. (If you’re not familiar with CSS, as I have to admit I wasn’t when I started looking at jQuery, then this is all new, but never mind.)

In order to try out some jQuery selectors, we need a page for it to work on. Here’s the body of a web page that has a few basic tags in it:

<body>
  <h2>jQuery Selectors</h2>
  <table>
    <tr>
      <th colspan="2">Comic Summary</th>
    </tr>
    <tr>
      <th>Comic</th>
      <th>Number</th>
    </tr>
    <tr>
      <td>Thor</td>
      <td>34</td>
    </tr>
    <tr>
      <td>Superman</td>
      <td>158</td>
    </tr>
    <tr>
      <td colspan="2">
        Which is best?<br />
        <label> <input type="radio" name="dcMarvel" /> DC</label>
        <label> <input type="radio" name="dcMarvel" /> Marvel</label>
      </td>
    </tr>
    <tr>
      <td colspan="2">
      What are your favourites?
        <ul>
          <li><label><input type="checkbox" />Batman</label></li>
          <li><label><input type="checkbox" />Superboy</label></li>
          <li><label><input type="checkbox" />Fantastic Four</label></li>
          <li><input type="checkbox" />Iron Man</li>
          <li><input type="checkbox" />Incredible Hulk</li>
          <li><input type="checkbox" />Green Lantern</li>
        </ul>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <input type="text" id="jqtest" /></td>
    </tr>
  </table>
</body>

This produces the following page:

For reference, this page has the simple style (specified in a CSS file):

body {
  background-color:lightgray;
  font-family:Arial;
}

Now, suppose we want to select all <li> tags. In this case, the jQuery call is simply $(‘li’). If you want test this out, you can create your own HTML file and put the above body into it, then add the following head section (before the body, of course):

<head>
  <title></title>
  <link href="Content/jQueryDemo.css" rel="stylesheet" />
  <script src="Scripts/jquery-1.8.2.js"></script>
  <script>
    $(function () {
      $('#jqtest').keypress(
        function (event) {
          if (event.keyCode === 13) {
            $('*').css({
              backgroundColor: 'lightgray',
              border: 'none'
            });
            console.log($($(this).val()));
            $($(this).val()).css({
              backgroundColor: 'palegreen',
              border: '1pt solid darkgreen'
            });
          }
        });
    });
  </script>
</head>

This assumes that you’ve got your CSS file in Content/jQueryDemo.css and that the jquery library is in Scripts/jquery-1.8.2.js. If you have a different version of jQuery or put your files in different places, you’ll need to modify those 2 lines in the header. If you’re using Visual Studio,  you can include jQuery as described in the last post.

As for the script in the header, don’t worry about it for now. Just be assured that when you type a query string into the text box and hit return, those page elements that you’ve selected will be highlighted in green.

Also, if you’re running a browser (such as Google Chrome) that has a console, you’ll see the selected elements printed out in the console. To activate Chrome’s console, right click on the page and select ‘Inspect element’, then click the Console tab. This is well worth doing, since not all of the selected elements get highlighted, and it’s reassuring to see that these elements have in fact been selected.

If you’ve got this page running, try typing li into the text box and hitting return. You should see this:

 

The 6 li elements have been highlighted. The reason that the top 3 don’t have their text highlighted is that these checkboxes are defined using the <label> tag, while the bottom 3 have a bare checkbox with some text after it. The label is a separate element that sits on top of the list, so it doesn’t get selected. Try typing label into the box and you’ll see just the top 3 checkboxes lit up, along with the 2 radio buttons.

If you want to select both li and label elements, enter li, label. That is, a comma separated list will select all elements that match any term in the list.

Although this is fairly simple, the results are global, in that you’re selecting all tags in the entire page. Suppose you wanted to select only those inputs that are inside labels. This time, you can type in label input (without a comma). (In this case, the display won’t show any items lit up, presumably because the label overwrites the input that it contains, but if you look in the console, you’ll see that the two radio buttons and top 3 checkboxes are selected.)

This form of list first selects the left-most tags (labels here) then selects children of those tags that satisfy the second condition. We could string together more tags if we have a deeper nesting on the page. Note that the input doesn’t have to be the immediate child of the label; if a label contains an input as its descendant at any point it will be selected.

If you want to restrict your choice to only immediate children, you can write td > label. This selects label tags that are immediate children of td tags. This will give you the 2 radio buttons, but not the top 3 checkboxes, since they are buried inside a ul and li tag. To compare, try typing td label (without the >) and this time you’ll get the top 3 checkboxes as well.

That’s about enough for a first post.

 

JSON with ASP.NET MVC 4

As a newcomer to JavaScript and jQuery, I wanted to write a (supposedly) simple little web site which used JSON (JavaScript Object Notation) to transmit information from a database to a web page. Surprisingly there didn’t seem to be any self-contained example or tutorial (that I could find) that showed how to do this basic operation. So here is the result of my attempt. It turns out that it is actually quite simple, once you know what to do.

First off, what is JSON? It is an alternative to XML as a way of sending information from one device to another. It’s a subset of the notation that can be used in JavaScript to define an object literal, which we saw in the last post. As an example, we might have some information on the numbers of various titles of comic books that are stored in a database. After we’ve retrieved this data from the database, we can encode it into JSON, so that it looks like this:

[
  {"Title":"Batman","Count":1},
  {"Title":"Fantastic Four","Count":2},
  {"Title":"Spider-man","Count":2},
  {"Title":"Superman","Count":1},
  {"Title":"Thor","Count":2}
]

That is, the data are stored as name-value pairs. In this case, each element in the array is actually a compound object consisting of two name-value pairs (Title and Count). We could have a simple list of single name-value pairs, or we could have deeper nesting of objects. There are various restrictions on the syntax for JSON objects, but as we’ll see, in MVC 4 you won’t usually have to write your own JSON, since there is a library routine that does it for you.

Now that we know what JSON is, how do we use it as a mediator between a database and a web page in ASP.NET MVC 4? We’ve seen that the procedure for generating web pages in MVC is as follows.

  1. Write a controller that contains a method that is called when a client requests a web page from the server.
  2. Write a view that is linked to the controller method, and which generates the markup that is returned to the client.

The controller method will usually collect some data from some other source, such as a database or some other C# code (which is usually part of the Model in MVC). This data is then packaged up, possibly in a C# object, and sent to the View, where the View formats the data and generates the HTML which is interpreted by the browser.

The procedure for using JSON doesn’t quite fit this pattern. Basically what happens is this:

  1. Client requests a web page.
  2. Controller method is called to process this request.
  3. The corresponding View is returned to the browser.
  4. The View contains some JavaScript code that makes another request to the server, this time asking for some data in JSON format.
  5. different Controller method from that called in step 2 is called to generate the JSON, which is returned to the browser.
  6. The JavaScript code processes the JSON and generates some HTML which is displayed.

The key point is that the JSON is not meant to be displayed as raw data by the browser; rather, it is retrieved by the browser and then processed on the client side before it is displayed.

We’ll illustrate this by showing how the data above can be obtained from the database and sent to a web page using JSON. First, we’ll add a controller to our ComicShop project that we’ve been using to demostrate things:

using System.Web.Mvc;
using ComicShop.Models;
using System.Collections.Generic;

namespace ComicShop.Controllers
{
  public class JsonController : Controller
  {
    //
    // GET: /Json/

    public ActionResult Index()
    {
      return View();
    }

    private IComicRepository comicRepository;

    public JsonController()
    {
      comicRepository = new ComicRepository();
    }

    public JsonController(IComicRepository comicRepository)
    {
      this.comicRepository = comicRepository;
    }

    public ViewResult JsonSummary()
    {
      return View();
    }

    public ActionResult Summary()
    {
      IEnumerable<ComicSummary> summaries = comicRepository.GetSummaries();
      return Json(summaries, JsonRequestBehavior.AllowGet);
    }

  }
}

This controller uses the IComicRepository interface and ComicRepository class that we introduced earlier. This controller contains two methods of interest here. The one called JsonSummary() simply returns a View, which is the View that requests the JSON data (we’ll get to this View in a moment).

The Summary() method is the one that produces the JSON data. The first line in this method requests the data from the database (see the earlier post for details of how this is done; all that’s important here is that we do get this data). The data is returned as an IEnumerable<ComicSummary> list. The ComicSummary class is defined as:

namespace ComicShop.Models
{
  public class ComicSummary
  {
    public string Title { get; set; }
    public int Count { get; set; }
  }
}

That is, it contains two data fields named Title and Count.

The second line in Summary() calls the library method Json() to create the JSON data. It is passed the list of ComicSummary objects in the variable summaries. The second parameter allows Summary() to provide JSON data in response to an HTTP Get request (by default, such a response is blocked for security reasons, so this parameter is needed). This returns the JSON string we gave above.

That’s all there is to producing JSON data (as promised, you didn’t have to actually write any raw JSON yourself, since the Json() method does it for you). If you want to verify that Summary() actually works, you can call it directly from a web browser by using the URL http://localhost:36195/Json/Summary (the port number for your localhost server will probably be different; what’s important is the path /Json/Summary), and you should see the raw JSON data printed in the browser.

Note that we did not associate a View with the Summary() controller method. As far as the browser is concerned, it is receiving raw text as a response to its request to Summary, so it just displays that. We need to do something special if we want it to interpret the JSON as data and incorporate it into a ‘real’ web page.

To that end, we turn our attention to the JsonSummary() controller method, and have a look at its View. This is in the file JsonSummary.cshtml:

<h2>JsonSummary</h2>
<script>
    $.getJSON('/Json/Summary',  function (data) {
        var items = [];
        $.each(data, function (key, val) {
            items.push('<li>' + key + ': ' + val.Title + ' (' + val.Count + ')</li>');
        });

        $('<ul/>', {
            html: items.join('')
        }).appendTo('body');
    });
</script>

As you can see, most of this file is JavaScript. However, it’s not all primitive JavaScript; it makes use of jQuery, so you need to make sure your web project has jQuery installed. If you started with an Empty project, you’ll need to do this yourself; if you started with a full Internet project, it will already be included.

To add in jQuery, right-click on the Solution in SolutionExplorer and select Manage NuGet Packages. Search in the Online section and find jQuery, then click Install. JSON should already be installed – you can check this by opening up References in SolutionExplorer and seeing that Newtonsoft.Json  is included in the list.

NuGet should take care of installing these packages and should find some jQuery JavaScript files in your Scripts folder (if you didn’t have a Scripts folder, it will be created by the installation).

We’re not quite done yet, though. In order for jQuery to be used in your View, that View needs to run the jQuery script. You could include a <script> tag in the View file itself, but if you plan on using jQuery in a lot of Views, it makes more sense to put it in the common layout file which we considered earlier. This file is called _Layout.cshtml and is in the Shared folder within the Views folder. Add the call to the jquery script in the <head> section of the layout. The modified _Layout.cshtml file looks like this:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <script src="~/Scripts/jquery-1.8.2.js"></script>
    <meta name="viewport" content="width=device-width" />
    <title>Comics</title>
</head>
<body>
    <h2>Comic Shop</h2>
    <div>
        @RenderBody()
    </div>
</body>
</html>

The call to the script is on line 9. The actual version number of jquery may differ from 1.8.2 if you install it later on, but just insert whatever version you got from NuGet.

That’s all we need to get the JavaScript to run, but there’s one more thing that’s very useful, and that’s to get Intellisense working for jQuery. Complete instructions for doing this are here, provided you’re using VS 2012. My _references.js file looks like this:

/// <reference path="jquery-1.8.2.intellisense.js" />
/// <reference path="jquery-1.8.2.js" />

Right, now we can look (finally) at JsonSummary.cshtml. A lot of the code there relies on a knowledge of JavaScript and jQuery syntax, so I won’t go through it in detail. However, I’ll mention a few key points so you can adapt it for your own purposes.

First, the $.getJSON() call is a jQuery method which makes a request to the URL given as its first argument for some JSON data. In our case, we use a relative URL /Json/Summary (the leading / is important: don’t leave it out!). If this call is successful, the JavaScript function given as the second argument to $.getJSON is called. (If the call fails, this function isn’t called, and you’ll get nothing on your web page apart from the HTML that is outside the <script> tag. This can make debugging a nightmare, since you won’t know what’s wrong, but never mind.)

The argument ‘data’ sent to this function is the JSON code. This function then constructs an array called ‘items’ by iterating through ‘data’ using the jQuery $.each() method. The second argument to $.each() is another function, this time taking two arguments. The ‘key’ argument is the integer index of the element from ‘data’ that is being processed, and ‘val’ is that actual element from ‘data’. Remember from the JSON above that each element in ‘data’ is a compound object of type ComicSummary, so it contains a Title and a Count field. We access these fields to create a HTML list entry on line 6, and push this onto the items array.

The last bit of code on lines 9 to 11 creates a <ul> tag and adds the items list to it, then it adds the <ul> tag to the body of the page. The final result looks like this:

JavaScript objects

After many years as an OO programmer using primarily C++, Java and C#, I’m finally taking a first look at JavaScript. At the lower syntax level, that of most operators, expressions, if statements and loops, JavaScript is much like other OO languages such as C# and Java. Above that level, things diverge quite rapidly. I’ll have a look at how JavaScript handles objects (in the OO sense) here.

One of the big differences between JavaScript and other mainstream OO languages (I’ll use C# as the main point of comparison from here on, as it’s the language I’m using for most other stuff) is that JavaScript is an untyped language. That is, you don’t need to (in fact, you can’t) specify the data type of a variable when it is declared. JavaScript has the ‘var’ keyword which should be used when declaring a variable. (I say ‘should be used’ since it is possible to declare a variable without using ‘var’, but this effectively makes the variable global, which is usually undesirable, so it’s best not to do it.)

However, JavaScript’s var is not the same as C#’s var. In C#, once a variable has been declared using var (or indeed, declared using any method), the data type of that variable is fixed. In the case of C#’s var, the data type is determined by the object to which that variable is initialized. In JavaScript, the data type of a variable is mutable, so you can, for example, declare a variable and assign a string to it, and later assign a different type such as a number. JavaScript is therefore loosely typed.

Another difference is that although objects are used in JavaScript, classes are not. This might seem contradictory; how can you have an object if it’s not an instance of a class? In this sense, JavaScript objects are similar to anonymous types in C#. An object can be created by simply listing some name-value pairs. For example, if we wanted an object that represents a book, we could write:

var bookObj = {
  author: "Delaney",
  title: "Nova",
  price: 5.47
}

This form of object is called an object literal, since it is a literal description of what one particular object contains. We could then use this object in a browser page by writing (assuming that the above code is stored in the file /Scripts/ObjectTest.js relative to the home page):

<h2>Books</h2>
<script src="~/Scripts/ObjectTest.js"></script>
<script>
    document.writeln(bookObj.author + ': <i>' + bookObj.title + '</i>  £' + bookObj.price + "<br>");
</script>

(We could, of course, have put the document.writeln() statement in the file as well, but this way we can see how to use the results of the first script in a script within the browser.)

This method is fine if we’re content to create single objects, but one of the powers of traditional OO languages is the ability to define a new data type (the class) and then create a number of objects of that data type. How do we do that in JavaScript?

It turns out that although JavaScript doesn’t have a class as such, it has a structure that, in practice, is very close to one, at least in the way it can be used. A class can be simulated in JavaScript by using a function.

A JavaScript function is actually an object in the same way that the untyped object above is. That is, a function can be created and passed around the program like any other object. In this sense, JavaScript functions are similar to C# delegates.

All objects in JavaScript have a prototype object behind them. This has a number of implications which we’ll get to in due course, but for now we can think of it as a form of inheritance. Just as all C# classes by default inherit the ‘object’ class, all object literals like the example above are backed by the Object.prototype object.

All functions are backed by Function.prototype, but each individual function also has its own prototype object behind it. This prototype can be used to add methods to a function.

Functions have a wide variety of uses, which we’ll get to in due course, but for now, the one we are interested in is the constructor function. This looks a lot like a class definition in C#. Here’s a constructor for a Book object:

var Book = function (author, title, price) {
  this.author = author;
  this.title = title;
  this.price = price;
};

Book.prototype.description = function () {
  return this.author + ': <i>' + this.title + '</i>  £' + this.price;
}

var book1 = new Book("Asimov", "Foundation", 3.55);
var book2 = new Book("Adams", "Hitchhiker's Guide to the Galaxy", 4.95);

The first 5 lines declare the constructor function, and define three data fields within it. All functions begin with the keyword ‘function’, followed by an argument list (which can be empty). As JavaScript doesn’t impose data types on its variables, this argument list contains no types, just parameter names.

The body of the constructor makes use of the keyword ‘this’. As in C#, ‘this’ refers to the object which called the function, so here, ‘this’ refers to the Book object that is being created. This code should look very similar to a constructor in C#.

Line 7 shows how to add a method to a Book object. We access the hidden prototype of the Book constructor, and then append the method name, which is ‘description’ here. The prototype is allowed to refer to ‘this’ in the same way as the original constructor. Here we just return a string containing some HTML to render the Book’s data in a browser.

The last two lines show how we can use the Book constructor to create a couple of objects. Again, these declarations look very similar to those in C#.

To use this code in a browser, we could put the following in the HTML file for the web page:

<h2>Books</h2>
<script src="~/Scripts/ObjectTest.js"></script>
<script>
    document.writeln(book1.description() + "<br>");
    document.writeln(book2.description() + "<br>");
</script>

Running the script from the file creates the book1 and book2 objects, and we can just call the description() method on them to obtain the HTML to render on the web page.

There are other ways of achieving the same result, but this little example should illustrate how JavaScript handles objects and object creation.

LINQ to XML: Creating an XElement

In the last post, we showed how to create a simple XML document in which the data were entered from a DataGrid. We gave the code for constructing the XML as follows:

    private XElement XmlFromLibrary()
    {
      ObservableCollection<Book> library = (ObservableCollection<Book>)((ObjectDataProvider)FindResource("LibraryGrid")).Data;
      XElement libraryElement =
        new XElement("LIBRARY",
          library.Select(book =>
            new XElement("BOOK",
              new XElement("AUTHOR", book.Author),
              new XElement("TITLE", book.Title),
              new XElement("PRICE", book.Price))));
      return libraryElement;
    }

The ‘library’ is fetched from a Windows resource defined in the XAML, with this resource being bound to the DataGrid (see earlier post for full details).

In writing this code, we glossed over some of the details of how the XElement is built. In fact, we used several techniques in this code that could do with further explanation.

The basic form of an XElement constructor is

XElement(XName name, params object[] content);

The first parameter gives the name of the XElement, which is used as the tag when writing out the XML. Usually, we’ll just enter a string here, and rely on the fact that the XElement constructor will convert this into an XName internally so we don’t need to worry about it.

The second parameter uses C#’s params keyword, which allows a variable number (one or more) of arguments to be passed to the constructor. As the data type of the content is just ‘object’, any data type  can be passed as the content of an XElement, and it’s here that the richness of the XElement class comes into play.

There are 8 specific data types that are handled in special ways when passed in as the content.

  1. A string is, as you might expect, just used as is as the content of the XML tag. (In fact, a string is converted into an XText object before it is used.)
  2. XText: This is a special class which is added as a child node of the XElement, but its value, which is a string, is used as the XElement’s text content.
  3. XCData: This allows insertion of the XML CData type, which consists of unparsed character data. Such strings may contain characters such as > and &, which ordinarily have a special meaning in XML syntax, but would be ignored here.
  4. XElement: The content can be another XElement, which is added as a child node to the parent XElement.
  5. XAttribute: This object is added as a child node, and represents an attribute of the parent node.
  6. XComment: Allows a comment to be attached to the XElement.
  7. IProcessingInstruction: Allows a processing instruction to be added to the XElement. (You don’t need to worry about these for most XML that you’ll write, but I may get back to them at some point.)
  8. IEnumerable: This is the magic data type, since it allows collections of data, such as those produced by LINQ query operations, to be passed in as content. The elements in the collection are iterated over, and each element is treated as a separate parameter. We used this feature in the code above to insert a list of Book objects into the XML using a LINQ Select() call.

In addition, you can also pass a null as the content (which does have its uses, though we won’t go into that here).

Finally, if the content is any other data type, the XElement will call the ToString() for that data type and use that as the content. This can cause some confusion, since there are some other LINQ to XML classes (such as XDocument) that are used to attach properties to the XML file that will be accepted as content for XElement, but rather than having the expected effect, XElement will just call its ToString() method and use that as content.

As a simple example, here’s some code that creates an XElement using most of the data types above as content:

using System;
using System.Xml.Linq;

namespace LinqXml03
{
  class Program
  {
    static void Main(string[] args)
    {
      XElement document = new XElement("Library",
        new XComment("This is a test library"),
        new XElement("Program", new Program()),
        new XElement("Book",
          new XElement("Author", "Isaac Asimov"),
          new XElement("Title", "I, Robot"),
          new XAttribute("Pages", 357)),
        new XElement("Book",
          new XElement("Author", "Samuel R. Delaney"),
          new XElement("Title", "Nova"),
          new XAttribute("Pages", 293)),
        new XCData("This contains a > and a & character"),
        new XText("This also contains a > and a & character"));
      Console.WriteLine(document);
   }
  }
}

This produces the output:

<Library>
  <!--This is a test library-->
  <Program>LinqXml03.Program</Program>
  <Book Pages="357">
    <Author>Isaac Asimov</Author>
    <Title>I, Robot</Title>
  </Book>
  <Book Pages="293">
    <Author>Samuel R. Delaney</Author>
    <Title>Nova</Title>
  </Book><![CDATA[This contains a > and a & character]]>This also contains a &gt; and a &amp; character</Library>

The top level XElement has the name ‘Library’. Its first content is a comment, which is written with the <!–…–> delimiters. Next, we’ve added a content object of type Program (that is, the class in which this program is written). The output is produced as a normal XElement tag, but the ToString() method is called from the Program class since it’s not one of the data types that has special meaning as an XElement content. The default ToString() method for a class just produces that class’s full pathname, which in this case is LinqXml03.Program.

Next, we add a couple of Book elements, each of which contains a couple of other XElements for the author and title. We’ve also added an XAttribute for the number of pages in the book.

The last two lines demonstrate the difference between XCData and XText. The XCData reproduces the given text exactly, and encloses it within the <![…]]> delimiters used for CData. The XText places the text as the content of the Library tag, and translates special characters into the XML code, so that > become &gt; and & becomes &amp;.

We’ve already seen an example of using IEnumerable in the code fragment at the top of this post.

LINQ for XML – the basics

LINQ provides a library of classes and methods that allow XML to be generated and imported quite easily (certainly more easily than with previous .NET libraries).

We’ll assume the reader is familiar with the basics of XML syntax and dive in with a simple little program that allows the user to enter some details for books in a library, then store this data to a disk file as XML (and of course to read in data from an XML file and display it).

The GUI is a WPF DataGrid and a menu for handling file operations, as shown:

We’ll represent the data internally using a Book class to represent each book, and an ObservableCollection to represent the collection of books. The data structures are similar to those that we used in discussing data binding to lists and combo boxes. The Book class is a bit simpler than it was there:

using System.ComponentModel;
namespace LinqXml02
{
  public class Book : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;
    protected void Notify(string propName)
    {
      if (this.PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }
    }

    string author;

    public string Author
    {
      get { return author; }
      set
      {
        author = value;
        Notify("Author");
      }
    }

    string title;

    public string Title
    {
      get { return title; }
      set
      {
        title = value;
        Notify("Title");
      }
    }

    decimal price;

    public decimal Price
    {
      get { return price; }
      set
      {
        price = value;
        Notify("Price");
      }
    }

    public Book() { }
    public Book(string author, string title, decimal price)
    {
      this.author = author;
      this.title = title;
      this.price = price;
    }
  }
}

The ObservableCollection is created in a special class called Library:

using System;
using System.Collections.ObjectModel;

namespace LinqXml02
{
  public class Library
  {
    Random rand = new Random();
    private decimal BookPrice()
    {
      decimal price = rand.Next(0, 5000) / 100m;
      return price;
    }

    public ObservableCollection<Book> GetLibrary()
    {
      ObservableCollection<Book> library = new ObservableCollection<Book>();
      return library;
    }
  }
}

This class serves as a resource in the XAML file:

<Window x:Class="LinqXml02.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:LinqXml02"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ObjectDataProvider x:Key="LibraryGrid"
                            ObjectType="{x:Type local:Library}"
                            MethodName="GetLibrary"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource LibraryGrid}" HorizontalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Menu VerticalAlignment="Top">
            <MenuItem Header="_File">
                <MenuItem x:Name="saveMenuItem" Header="_Save" HorizontalAlignment="Left" Width="145" Click="saveMenuItem_Click"/>
                <MenuItem x:Name="saveAsMenuItem" Header="Save _as" HorizontalAlignment="Left" Width="145" Click="saveAsMenuItem_Click"/>
                <MenuItem x:Name="openMenuItem" Header="_Open" HorizontalAlignment="Left" Width="145" Click="openMenuItem_Click"/>
                <Separator HorizontalAlignment="Left" Width="145"/>
                <MenuItem x:Name="exitMenuItem" Header="E_xit" HorizontalAlignment="Left" Width="145" Click="exitMenuItem_Click"/>
            </MenuItem>
        </Menu>
        <DataGrid x:Name="bookGrid" Grid.Row="1" ItemsSource="{Binding}" AutoGenerateColumns="False"  HorizontalAlignment="Stretch">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Author" Binding="{Binding Author}" Width="45*"/>
                <DataGridTextColumn Header="Title" Binding="{Binding Title}"  Width="45*"/>
                <DataGridTextColumn Header="Price" Binding="{Binding Price}"  Width="10*"/>
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>

On lines 7 to 9 we create the resource, then use it as the data context for the Grid on line 11. The DataGrid defined on line 25 uses this data context as the binding for its ItemsSource property, and then we define the three columns, each bound to a property in the Book class. We could have used the auto-generate column feature of a DataGrid, but that doesn’t allow us to customize the widths of the columns, which we’ve done here by assigning each of the Author and Title columns 45% of the horizontal width, with Price getting the remaining 10%.

With the data structures set up and the binding in place, we could run the program and enter some book data, and the data binding will automatically update the ObservableCollection as we enter data into the DataGrid. However, at this stage we have no way of saving the data thus entered. For that we introduce the XML.

First, we’ll have a look at the event handlers for the Save and Save As menu items.

    string saveFilename = "";
    private void saveAsMenuItem_Click(object sender, RoutedEventArgs e)
    {
      SaveFileDialog saveDialog = new SaveFileDialog();
      saveDialog.Filter = "XML file|*.xml";
      saveDialog.Title = "Save library";
      if (saveDialog.ShowDialog() == true)
      {
        saveFilename = saveDialog.FileName;
        saveMenuItem_Click(sender, e);
        Title = "Library - " + saveDialog.FileName;
      }
    }

    private void saveMenuItem_Click(object sender, RoutedEventArgs e)
    {
      if (saveFilename.Equals(""))
      {
        saveAsMenuItem_Click(sender, e);
      }
      else
      {
        XElement saveLibraryXml = XmlFromLibrary();
        saveLibraryXml.Save(saveFilename);
      }
    }

The SaveFileDialog (and OpenFileDialog) classes are in the old Microsoft.Win32 namespace, but they still seem to work well enough. In order to allow us to save changes to a currently open file, we have an auxiliary string called saveFilename. If this string has zero length, then we open the SaveFileDialog to get the user to select a filename. The dialog has a filter that displays only .xml files.

Once a file has been chosen, the saveMenuItem_Click() handler is called, and the method XmlFromLibrary() is called. We’ll consider this in a moment, but first we need to describe the XElement class.

In LINQ’s handling of XML, all XML tags are represented by XElement objects. There is no need for a separate, top-level document object in which to place the XElements; XElement itself can serve as the top level, and all lower levels.

Nested tags in the XML are represented simply as nested XElement objects. This gives the C# code a structure that is easy to understand for the human reader.

Now we can have a look at XmlFromLibrary():

    private XElement XmlFromLibrary()
    {
      ObservableCollection<Book> library = (ObservableCollection<Book>)((ObjectDataProvider)FindResource("LibraryGrid")).Data;
      XElement libraryElement =
        new XElement("LIBRARY",
          library.Select(book =>
            new XElement("BOOK",
              new XElement("AUTHOR", book.Author),
              new XElement("TITLE", book.Title),
              new XElement("PRICE", book.Price))));
      return libraryElement;
    }

After retrieving ‘library’ from the Windows resources, we create the XML representation of the library with a single C# statement. The top level object is libraryElement, which is given the tag LIBRARY. The second argument to its contructor is built using a LINQ Select() call on library. Remember that library consists of a list of Book objects, so we simply iterate through each Book in the list, and construct a new XElement for each Book. Within the Book’s XElement, we add 3 more XElements for the Author, Title and Price fields.

And that’s it. The code is very clean. Back in saveMenuItem_Click(), we simply call the Save() method from the XElement object to save the file to disk. The resulting file for the books shown in the picture above is:

<?xml version="1.0" encoding="utf-8"?>
<LIBRARY>
  <BOOK>
    <AUTHOR>Asimov, Isaac</AUTHOR>
    <TITLE>I, Robot</TITLE>
    <PRICE>3.50</PRICE>
  </BOOK>
  <BOOK>
    <AUTHOR>Niven, Larry</AUTHOR>
    <TITLE>Ringworld</TITLE>
    <PRICE>4.95</PRICE>
  </BOOK>
  <BOOK>
    <AUTHOR>Asimov, Isaac</AUTHOR>
    <TITLE>Foundation</TITLE>
    <PRICE>2.25</PRICE>
  </BOOK>
  <BOOK>
    <AUTHOR>Simak, Clifford D.</AUTHOR>
    <TITLE>Buckets of Diamonds</TITLE>
    <PRICE>5.00</PRICE>
  </BOOK>
</LIBRARY>

The Save() method produces the usual first line of an XML file, and then writes out the XML itself, all neatly indented.

To read the XML file back into the program, we need to construct the internal ObservableCollection from the XML. This is almost as easy as producing the XML in the first place. Here’s the code for the Open menu item, and the associated LibraryFromXml() method that reads the XML:

    private void openMenuItem_Click(object sender, RoutedEventArgs e)
    {
      OpenFileDialog openDialog = new OpenFileDialog();
      openDialog.DefaultExt = ".xml";
      openDialog.Filter = "XML documents (.xml)|*.xml";
      bool? result = openDialog.ShowDialog();
      if (result == true)
      {
        XElement libraryXml = XElement.Load(openDialog.FileName);
        Title = "Library - " + openDialog.FileName;
        LibraryFromXml(libraryXml);
        saveFilename = openDialog.FileName;
      }
    }

    private void LibraryFromXml(XElement libraryXml)
    {
      ObservableCollection<Book> library = (ObservableCollection<Book>)((ObjectDataProvider)FindResource("LibraryGrid")).Data;
      library.Clear();
      var bookElements = libraryXml.Elements("BOOK");
      foreach (XElement book in bookElements)
      {
        Book addBook = new Book(
          (string)book.Element("AUTHOR"),
          (string)book.Element("TITLE"),
          (decimal)book.Element("PRICE"));
        library.Add(addBook);
      }
    }

In the openMenuItem_Click() handler, we use the static XElement.Load() method to read the XML from the file into an XElement.

In LibraryFromXml() we again retrieve the library resource and clear it of existing data. Then we call the Elements() method on the XElement to retrieve a list of BOOK tags. This produces an IEnumerable list of XElements for the BOOK objects in the original XML. For each of these, we simply create a Book object by extracting the AUTHOR, TITLE and PRICE XElements for each BOOK, and then add this Book object to the library. The data binding takes care of the rest, so the DataGrid is automatically updated to display the list of books we read in.

There’s a lot more that can be done with LINQ and XML, but this little example should show you that for saving and reading basic XML, LINQ is easy to use.

Code for this post available here.

LINQ: ToLookup

We’ve seen how to create a Dictionary using LINQ. A Dictionary is a hash table in which only one object may be stored for each key. It can also be useful to store more than one object for a given key, and for that, the C# Lookup<> (part of the System.Linq namespace) generic type can be used.

LINQ provides the ToLookup() method for creating Lookups. It works in much the same way as ToDictionary(), except that as many objects as you like can be attached to each key.

Returning to our example using Canadian prime ministers, we can create a Lookup in which the key is the first letter of the prime minister’s last name. The code is

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
      var pmLookup01 = primeMinisters.ToLookup(pm => pm.lastName[0]);
      var keys01 = pmLookup01.Select(pm => pm.Key).OrderBy(key => key);
      Console.WriteLine("----->pmLookup01");
      foreach (var key in keys01)
      {
        Console.WriteLine("PMs starting with {0}", key);
        foreach (var pm in pmLookup01[key])
        {
          Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
        }
      }

This is the simplest version of ToLookup(). The method takes a single argument, which is a function specifying how to calculate the key. In this case, we just take the first char in the string pm.lastName.

For some reason, the Lookup class doesn’t contain a property for retrieving the list of keys, so we need to use a roundabout method to get them. Line 5 uses a Select() to retrieve the keys and an OrderBy() to sort them into alphabetical order. We can then iterate over the keys and, for each key, we can iterate over the prime ministers for that key. Note that the object pmLookup01[key] is not a single object; rather it contains a list of all prime ministers whose last name begins with the letter contained in the key.

The output from this code is:

----->pmLookup01
PMs starting with A
  -  Abbott, John
PMs starting with B
  -  Bowell, Mackenzie
  -  Borden, Robert
  -  Bennett, Richard
PMs starting with C
  -  Clark, Joe
  -  Campbell, Kim
  -  Chrétien, Jean
PMs starting with D
  -  Diefenbaker, John
PMs starting with H
  -  Harper, Stephen
PMs starting with L
  -  Laurier, Wilfrid
PMs starting with M
  -  Macdonald, John
  -  Mackenzie, Alexander
  -  Meighen, Arthur
  -  Mackenzie King, William
  -  Mulroney, Brian
  -  Martin, Paul
PMs starting with P
  -  Pearson, Lester
PMs starting with S
  -  St. Laurent, Louis
PMs starting with T
  -  Thompson, John
  -  Tupper, Charles
  -  Trudeau, Pierre
  -  Turner, John

We can do the same thing using the second form of ToLookup(), which allows us to specify an EqualityComparer to be used in determining which keys are equal. The comparer class looks like this:

using System.Collections.Generic;

namespace LinqObjects01
{
  class LookupComparer : IEqualityComparer<string>
  {
    public bool Equals(string x, string y)
    {
      return x[0] == y[0];
    }

    public int GetHashCode(string obj)
    {
      return obj[0].GetHashCode();
    }
  }
}

This comparer compares two strings and says they are equal if their first characters are equal. Using this class, we can apply the second form of ToLookup():

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
      var pmLookup02 = primeMinisters.ToLookup(pm => pm.lastName,
        new LookupComparer());
      var keys02 = pmLookup02.Select(pm => pm.Key).OrderBy(key => key);
      Console.WriteLine("----->pmLookup02");
      foreach (var key in keys02)
      {
        Console.WriteLine("PMs starting with {0}", key[0]);
        foreach (var pm in pmLookup02[key])
        {
          Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
        }
      }

The first argument to ToLookup() now passes the entire pm.lastName, and the second argument to ToLookup() is the comparer object.

When we print out the results, we have to remember that the key for each entry in the Lookup is now the full last name of the first prime minister encountered whose name starts with a given letter. Thus if we printed out the full key, we’d get a full last name. That’s why we print out key[0] on line 8; that way we get the first letter of the name.

The third version of ToLookup() allows us to specify a custom data type to return. If we wanted just the first and last names of each prime minister, for example, we could write:

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
      var pmLookup03 = primeMinisters.ToLookup(pm => pm.lastName[0],
        pm => new
        {
          lastName = pm.lastName,
          firstName = pm.firstName
        });
      var keys03 = pmLookup03.Select(pm => pm.Key).OrderBy(key => key);
      Console.WriteLine("----->pmLookup03");
      foreach (var key in keys03)
      {
        Console.WriteLine("PMs starting with {0}", key);
        foreach (var pm in pmLookup03[key])
        {
          Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
        }
      }

We’ve returned to using the first letter of the last name as the key (that is, there’s no comparer), and passed in an anonymous data type as the second argument to ToLookup(). Apart from that, the code is the same as in the first example.

Finally, the fourth version allows us to specify both a custom data type and a comparer, so we can combine that last two examples to get this:

      PrimeMinisters[] primeMinisters = PrimeMinisters.GetPrimeMinistersArray();
       var pmLookup04 = primeMinisters.ToLookup(pm => pm.lastName,
       pm => new
        {
          lastName = pm.lastName,
          firstName = pm.firstName
        },
        new LookupComparer());
       var keys04 = pmLookup04.Select(pm => pm.Key).OrderBy(key => key);
       Console.WriteLine("----->pmLookup04");
       foreach (var key in keys04)
       {
         Console.WriteLine("PMs starting with {0}", key[0]);
         foreach (var pm in pmLookup04[key])
         {
           Console.WriteLine("  -  {0}, {1}", pm.lastName, pm.firstName);
         }
       }

Now we’re back to using the full last name as the key, since the comparer does the checking for matching first letters. Just make sure you pass in the arguments in the right order: (1) choose key; (2) choose custom data type; (3) choose comparer.

Hyperlink columns: displaying the link in a browser

A while back I posted an article on how to use the WPF DataGridHyperlinkColumn. There, the web page referenced by the hyperlink was displayed in the application’s own window, using WPF’s internal web browser. This browser has a lot of limitations, and it’s more usual for links like these to lead to the page being displayed in the user’s favourite web browser.

This post shows the modifications we need to make to have this happen.

The first thing we need to do (assuming we don’t want the page to show up in the application’s own window as well) is convert all uses of the NavigationWindow back to a normal Window. This is fairly safe to do by using a global find and replace in Visual Studio. Typically, NavigationWindow is used only in the XAML file and in the behind code for this file (where it serves as the base class for the MainWindow class). This will prevent the web page from appearing in the application itself.

To get the link to show up in the default browser, we need to add an explicit event handler to the DataGridHyperlinkColumn. If we modify the hyperlink column we used in our earlier example of a comic book database application, the XAML now looks like this:

                                <DataGridHyperlinkColumn  Header="ComicVine" Binding="{Binding ComicVine}"
                                        ContentBinding="{Binding ComicVine, Converter={StaticResource ComicVineConverter}}"
                                          Width="67">
                                    <DataGridHyperlinkColumn.ElementStyle>
                                        <Style>
                                            <EventSetter Event="Hyperlink.Click" Handler="WebPageClick"/>
                                        </Style>
                                    </DataGridHyperlinkColumn.ElementStyle>
                                </DataGridHyperlinkColumn>

The properties of the hyperlink column itself are the same as before. The change is that we’ve added an ElementStyle section, in which we’ve provided a link to a handler for the Hyperlink.Click event. This handler is in the MainWindow class and looks like this:

    private void WebPageClick(object sender, RoutedEventArgs e)
    {
      Hyperlink link = e.OriginalSource as Hyperlink;
      Process.Start(link.NavigateUri.AbsoluteUri);
    }

This code retrieves the hyperlink that was clicked, and then starts an external process by calling Process.Start() with the hyperlink as the argument. This uses Windows’ association of file type to application, so if your default browser is, say, Google Chrome, then sending a URI to Process.Start() will cause Chrome to be started and sent the URI to display.

In order for this code to work, you’ll need a couple of ‘using’ statements at the top:

using System.Diagnostics;
using System.Windows.Documents;

That’s all there is to it.