Welcome to MSDN Blogs Sign in | Join | Help

Mike Ormond's Blog

In my world, things would be simpler than this...
Dynamically Loading ListView Templates

I received an email question recently from a customer asking how they could dynamically load the LayoutTemplate for a ListView from a UserControl. I banged my head on this one for a while and eventually mailed our internal ASP.NET alias asking if someone could help. Fortunately David Fowler could. Hats off to him - the code below is his solution.

Let's start with a basic ListView page that we want to convert to load the LayoutTemplate from a UserControl. Something like this will do:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server"></head>
<body>
  <form id="form1" runat="server">
    <asp:ListView ID="ListView1" runat="server"
      DataSourceID="XmlDataSource1">
      <LayoutTemplate>
        <ul>
          <asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
        </ul>
      </LayoutTemplate>
      <ItemTemplate>
        <li><%# Eval("id") %></li>
      </ItemTemplate>
    </asp:ListView>
    <asp:XmlDataSource ID="XmlDataSource1" runat="server"
      XPath="/catalog/book"
      DataFile="~/XMLFile.xml">
    </asp:XmlDataSource>
  </form>
</body>
</html>

We have an XmlDataSource (in my case pointing to the MSDN sample XML file) and I'm binding the book ids to list items in an unordered list using a ListView control. Pretty straightforward so far.

Imagine I refactored this a little to use a UserControl for the LayoutTemplate

<%@ Control Language="C#" %>
<ul>
  <asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
</ul>

and one for the ItemTemplate

<%@ Control Language="C#" %>
<li>
  <%# Eval("id") %>
</li>

That means I could replace my original aspx file with one that looks like this

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
</head>
<body>
  <form id="form1" runat="server">
    <asp:ListView ID="ListView1" runat="server" 
      ItemPlaceholderID="MyLayout$itemPlaceholder"
      DataSourceID="XmlDataSource1">
    </asp:ListView>
    <asp:XmlDataSource ID="XmlDataSource1" runat="server" 
      XPath="/catalog/book"
      DataFile="~/XMLFile.xml">
    </asp:XmlDataSource>
  </form>
</body>
</html>

ie I've defined no LayoutTemplate or ItemTemplate - we'll load these dynamically. The only other change is I've specified an ItemPlaceholderID on the ListView. We'll see why in a second.

using System;
using System.Web.UI;

public partial class Default2 : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    ListView1.LayoutCreated += new EventHandler(ListView1_LayoutCreated);
    ListView1.LayoutTemplate = LoadTemplate("LayoutTemplate.ascx");
    ListView1.ItemTemplate = LoadTemplate("ItemTemplate.ascx");
  }

  void ListView1_LayoutCreated(object sender, EventArgs e)
  {
    //remove the layout template
    ListView1.Controls.RemoveAt(0);

    //recreate it
    Control newLayoutContainer = new Control();
    ListView1.LayoutTemplate.InstantiateIn(newLayoutContainer);
    var userControl = newLayoutContainer.Controls[0];
    userControl.ID = "MyLayout";
    ListView1.Controls.Add(newLayoutContainer);
  }
}

image If you just go ahead and load the templates from the UserControls, you'll get the yellow screen of death telling you "An item placeholder must be specified on ListView 'ListView1'. Specify an item placeholder by setting a control's ID property to "itemPlaceholder". The item placeholder control must also specify runat="server"." The ListView simply can't find the ItemPlaceholder.

The key here is that the UserControl is a naming container so the ListView can't find the ItemPlaceholderID because it's been modified to avoid naming clashes on the page. In the code above we recreate the LayoutTemplate and set the UserControl's ID to "MyLayout" allowing us to specify that the ItemPlaceholderID will be "MyLayout$itemPlaceholder".

You could reduce this by determining up front the "native" ID of the UserControl ("ctl01" in this case) and setting the ItemPlaceholderID property of the ListView to "ctl01$itemPlaceholder". This would allow you to dispense with the LayoutCreated handler altogether. Of course if your UserControl ID then changes, it's going to break.

Technorati Tags: ,
Will the real Windows Vista please stand up?

Undoubtedly, damage was done to Vista's reputation in the early days after launch. And inevitably such damage was amplified by the "social networking" effect, particularly as a result of Apple's very effective Mac ads which poked fun not just at the platform but at the people that chose to use it.

How one recovers from a perception issue is an interesting question. Perception *is* ultimately more important than reality, at least where brands are concerned, and such negative perceptions taking a long time to shake off. A new Vista ad campaign has been much reported in the press. Then yesterday, Ina Fried on CNET News reports on an interesting experiment with XP users who had "negative impressions of Vista". An fascinating thought not altogether surprising outcome but will it help sway people? I fear not.

It's going to be a tough, uphill struggle and we (Microsoft) need to ensure we don't (regularly) shoot ourselves in the foot as we make the climb. A while back a customer challenged me on why I would choose Vista over XP. I replied:

"Many reasons. I run a number of machines and wherever I can I choose Vista. (I have, for example, a relatively old Windows Media Center PC which wouldn't run Vista successfully - there was a device driver issue resulting in the OS being swamped by interrupts so I had to revert it to XP). I like User Account Control very much and the fact I can easily elevate my privileges as required. This is just a pain to manage on XP machines. I also rely on the integrated search capabilities, the mobility centre, the way metadata is surfaced in Explorer. And I do like Windows Aero :-). All in all I just find most things easier to do in Windows Vista. That's not to say I think it's perfect but in my experience Vista has been solid, reliable, secure, productive and fast."

That last statement about "solid, reliable, secure, productive and fast" is the one I most often lose sight of. No question Vista is a better experience for me than XP. Yeah it does some odd things from time to time that make me roll me eyes but overall it's fantastic. I can't do any sort of comparison with a Mac, I don't own one and don't intend to. In any case this wasn't meant to be about Mac vs PC but Vista vs Vista.

Technorati Tags: ,
Getting Twitter Updates On My Blog

Yes, I have started Twittering or Tweeting or whatever you call it (you can see my Tweets here) and immediately I wanted to update my blog to [a] show a "Follow Me" link and [b] show my latest tweets. As I'm hosted on blogs.msdn.com, I don't have much control over my blog. Essentially I can override the Title, News and Header, apply a different Skin and add some CSS Overrides. What I can't do is directly modify the skin content so a little effort is required to, for example, add something to the navigation.

What we need is a little Javascript to modify the DOM (after it's loaded but ideally we don't want to wait for images to load) and add some extra elements in the appropriate place. I thought this would be a good opportunity to have a play around with some of the Javascript frameworks out there. I started with jQuery.

I have to say those guys have done a brilliant job with documentation and conceptually it's easy to pick up and be productive quickly. The $(document).ready(function) function allows me to hook up my code so it starts to execute when the DOM is ready to go. It didn't take me long to piece together enough bits to add the "Follow me on Twitter" link into the navbar above.

DSCF2293At that point I decided I also wanted to incorporate Lightbox2, a very cool way to overlay images on the page (click the image on the right and a higher res image will open with Lightbox2). Lightbox2 however, makes use of Prototype and Scriptaculous. For one thing I was starting to have a dependency on a lot of JS libraries and for another I had a conflict. jQuery.noConflict( ) sorted out my conflict problem but I realised that, as I needed Prototype for Lightbox2, I should probably just make use of it for everything else. Bye bye jQuery (sorry jQuery, I liked you). Hello Prototype.

I'll be honest, I don't think the docs for Prototype are quite as good as jQuery and it took me a little longer to get going but the things I'm doing aren't radically different in the two so it didn't take me long to port my code. Just for reference, Prototype uses document.observe("dom:loaded", function) to hook DOM ready.

That was the easy bit over. Next I wanted to display my recent Tweets and I stumbled across the excellent Twitter.js script from Remy Sharp. This implements a similar mechanism to jQuery for determining when the DOM is loaded so in fact it's overkill in my case (as I don't call it until I know the DOM is ready). I might get around to sorting this out one day but for now it'll do. The script is very neat and allows you to set various parameters and a template that will be populated with your tweets. The Twitter API is less neat. There seems to be no way to specify that you only want specific items or fields so you end up transferring a very heavy JSON lump to the client and throwing about 95% of it away in my case.

At this point I had tweets on my blog. However I soon I noticed that all was okay in Firefox but things were less reliable in IE. Often the tweets would never load. Much head scratching and debugging ensued and eventually I ended up staring at Fiddler traces trying to figure out why one worked and one didn't.

I got a bit lucky here as I quickly spotted a header that existed in the IE call but not in the FF one: If-Modified-Since. Twitter was responding with a 200 OK (rather than a 304 Not Modified) and an empty response body. A bit odd - the way the Twitter.js script works is, the response is supposed to contain a JS function call that renders the JSON payload. So empty response = no function call = no tweets. I then spotted the following in the Twitter API documentation for the user_timeline call (my colouring):

"Parameter: since.  Optional.  Narrows the returned results to just those statuses created after the specified HTTP-formatted date.  The same behavior is available by setting an If-Modified-Since header in your HTTP request.  Ex: http://twitter.com/statuses/user_timeline.rss?since=Tue%2C+27+Mar+2007+22%3A55%3A48+GMT"

The If-Modified-Since header is being interpreted as the "since" parameter on the user_timeline API call giving me only the tweets since the last time IE visited. Not really what I wanted. To fix this I appended a since paramater and set it to a date one week in the past. Now I have both IE and Firefox working happily.

Virtual Earth - Finding Multiple Locations

imageOf course, once you've found one postcode, you find yourself a reason to find lots of them as Ashley [no link] found out. You could do something like the below (which plots all the locations in postcodeArray and even labels them this time). The pushpins are added to an array before being added to the map in a single call to map.AddShape().

You need to call map.Find() sequentially. From the MSDN documentation "The callback function for this method is not re-entrant. If an application calls Find before a previous Find call has returned the search results to the callback function, the first set of arguments are destroyed and are no longer available."

In the anonymous function (in the call to map.Find()) I check if we're at the end of the array and call FindLocation() again if there are more postcodes to process. Of course these don't have to be postcodes - they could be any form of location but at least for a postcode you shouldn't need to worry about disambiguation. This technique is going to result in a deep call stack if you have a lot of locations so you'd want to refactor this code if that's the case.

It feels like there ought to be an easier way to do this as it's a common requirement. If anyone knows of one please chip in. Or if the Live team are listening....

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <script type="text/javascript" 
    src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1"></script>

  <script type="text/javascript">
    var map = null;
    var postcodeLayer = null;
    var pushpinArray = null;
    var postcodeArray = ['RG6 1WG', 'RG1 2PY', 'RG30 2DG'];

    function GetMap() {
      map = new VEMap('myMap');
      pushpinArray = new Array();
      postcodeLayer = new VEShapeLayer();
      map.LoadMap();
      FindLocation(0);
    }

    function FindLocation(locationCount) {

      try {
        map.Find(null, postcodeArray[locationCount],
                 null, null, null, null, null, null,
                 false, true,

        function() {
          var pPin = new VEShape(VEShapeType.Pushpin, map.GetCenter());
          pPin.SetTitle(postcodeArray[locationCount]);
          pushpinArray[locationCount] = pPin;

          if (locationCount++ < postcodeArray.length - 1) {
            FindLocation(locationCount);
          }
          else {
            map.AddShape(pushpinArray);
            document.getElementById('myMap').style.visibility = 'visible';
          }
        }

        );
      }
      catch (e) {
        alert(e.message);
      }
    }

  </script>

</head>
<body onload="GetMap();">
  <div id='myMap' style="position: relative; width: 400px; height: 400px; visibility: hidden;">
  </div>
</body>
</html>
Technorati Tags: ,
Upcoming Events

I've just been going through my diary to make sure everything is up to date and thought it might be worthwhile posting a list of events I'll be speaking at in the near future while things are fresh in my mind.

Many of these events aren't open for registration yet so if you want to come along, make sure you keep an eye on the relevant page or subscribe to the feed. I haven't included ReMix UK 08 as I'm not sure whether or not I'll be speaking there. I've allocated myself the job of "fallback boy" for ReMix so I could end up doing anything (or nothing) depending on the final tweaks to the agenda. That'll keep me on my toes.

Event Title When Where
Vista Squad: Silverlight 2 – What’s new in Beta 2 20/08/2008 London
MSDN Event: Rich Internet Applications with Visual Studio 2008 Service Pack 1 02/09/2008 TVP (Reading)
MSDN Event: Rich Internet Applications with Visual Studio 2008 Service Pack 1 04/09/2008 London
Developer Group: Silverlight 2 08/09/2008 TVP
QBS Seminar: ASP.NET Dynamic Data 17/09/2008 TVP
QBS Seminar: ASP.NET Dynamic Data 24/09/2008 TVP
MSDN Event: What’s New in Visual Studio 2008 Service Pack 1? 02/10/2008 TVP
MSDN Event: What’s New in Visual Studio 2008 Service Pack 1? 22/10/2008 Bristol
MSDN Event: What’s New in Visual Studio 2008 Service Pack 1? 23/10/2008 Exeter
MSDN Roadshow Re-Run 24/10/2008 London

ReMix UK 08 Developer Track

clip_image001

Things are starting to shape up nicely on the developer track so I thought I'd try and give you a flavour of what you'll see if (surely "when"?) you join us in Brighton in September for ReMix UK. There'll be a big focus on rich client with Silverlight, WPF and IE8 featuring prominently. You can also expect to hear a lot about data and getting stuff into and out of your shiny new client. On top of that there'll be plenty of ASP.NET, some Visual Studio IDE Tips and Tricks and some stuff nobody's bothered to tell me about.

From a speaker perspective we'll have author, raconteur and real-ale fan Jesse Liberty, top speaker, scratch handicap golfer and raconteur Mike Taulty, data wizard, county cricket record holder (Somerset) and raconteur Mike Flasko, browser guru, free-diving champion and supreme raconteur Travis Leithead, enormous blogger, Olympic weightlifter and raconteur Sara Ford as well as Scott Guthrie. Remember him?

Of course contents may settle in transit, all of the above is subject to change and some of it I simply made up (but I can, hand on heart, say that all those people are due to speak on the Developer Track at ReMix UK 08 and I'm pretty excited about it!)

I even managed to gather a few of them together for a group photo.

image

I'm so impressed with the results I'm beginning to wonder whether it was really the Designer Track they meant to put me in charge of...

I'm sorry Mike - people don't often get to see those legs.

Virtual Earth - Finding a Postcode

I'm a big fan of Virtual Earth and often try and sneak it into demos as many people seem unaware of its existence or unaware of just how good it is. A common question I get is "Do I need to use lat / lon or can I plot a postcode?". Absolutely you can plot a postcode - the big advantage of having lat / lon is being able to pin point *exactly* where something is (and probably a little less overhead).

Here's an HTML page that uses the Virtual Earth map control to plot the location of the Microsoft Reading office postcode (RG6 1WG). You can just cut and paste the below into an HTML document to see it working. Note the reference to v6.1 of the map control script and the use of a callback on map.Find() to plot the pushpin.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  
  <script type="text/javascript" 
    src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1"></script>
    
  <script type="text/javascript">
    var map = null;
    
    function GetMap() {
      map = new VEMap('myMap');
      map.LoadMap();
      FindLoc();
    }

    function FindLoc() {
      try {
        map.Find(null, 'RG6 1WG', null, null, null, null, null, null, false, true, LocFound);
      }
      catch (e) {
        alert(e.message);
      }
    }

    function LocFound() {
      var pPin = map.AddPushpin(map.GetCenter());
    }  
  </script>

</head>
<body onload="GetMap();">
  <div id='myMap' style="position: relative; width: 400px; height: 400px;">
  </div>
</body>
</html>

[UPDATE]

As Graham points out in the comments on this post, the above code will momentarily show the default map before displaying the postcode. To avoid this you have a couple of options, one is to hide the map until you're ready to display it. Here's a modified snippet of the above code that would achieve that:

    function LocFound() {
      var pPin = map.AddPushpin(map.GetCenter());
      document.getElementById('myMap').style.visibility = 'visible';
    }  
  </script>

</head>
<body onload="GetMap();">
  <div id='myMap' style="position: relative; width: 400px; height: 400px;visibility: hidden;">
  </div>
</body>

All I've done is changed 'myMap' to be hidden by default and added a line of code to the LocFound() method to make it visible when we've got the postcode location and are ready to display the map.

image

Loading the above HTML document in a browser will result in something similar to that on the left (click the image to see full size).

You might also want to take a look at the Vista Gadget I created some time ago which will take a location (including a postcode) or a route and plot it on a "flyout" Virtual Earth map. You can download it and pull the script apart to see how it works.

 

Technorati Tags: ,
Diffing Open XML Files

I don't do so much with Open XML these days but I still get a few questions from people and I'm still on some of the internal aliases. A recent message from Eric White caught my eye. "Pranav Wagh has built a much improved version of OpenXmlDiff, with a graphical user interface." TBH, I don't think the original "unimproved" version was around when I was messing with Open XML. This would have been a very handy utility to have to hand, especially when my System.IO.Packaging code went slightly awry. If you're working with Open XML, I suggest taking a look with a view to adding it to your "useful utilities" toolbox.

Technorati Tags: ,
Twittering

I am on the verge of Twittering. I still don't get it and the more "I just swatted a fly" tweets I see on there the less I get it. But I have this sort of itch that says *unless* I try it I just wont get it. And unless I try it I may be missing out on something special, some sort of communications revolution. Yet something still holds me back.

A big part of my job is communications; trying to connect with lots of different people in lots of different ways. Maybe they see me at an event. Maybe they stop and have a chat. Maybe they drop me a mail (mike dot ormond at microsoft dot com). Maybe they watch a screencast. Maybe they read this blog.

But much of that communication tends to be a "broadcast" and not necessarily conducive to conversation. That's frustrating (for me at least). Does Twitter help in this regard? If I resist the temptation to tweet about the humdrum of everyday life (yesterday you could have read about the bad smell I noticed upstairs, followed by a gruesome mouse discovery under the bed (the cat has a lot to answer for) and the stomach-churning disposal process that followed - I guess in Twitter that could be 3 or 4 graphic instalments as I moved from phase to phase). If I resist that, does it offer a new channel to express myself and more importantly, to connect to people?

I know I'm not the first to perch on the fence but I'm undecided. Maybe tomorrow I'll take the plunge...

Technorati Tags:
ASP.NET AJAX Roadmap

In case you haven't seen it, we've published our roadmap for ASP.NET AJAX on Codeplex and there's an associated thread for feedback here. If AJAX is your thing then please have a read and provide feedback - now's the time if you want to steer the shape of future releases.

The roadmap runs to 10 or so pages so I wont try and summarise everything here but it includes proposals such as improvements to the DOM APIs including support for native querySelector APIs, client data and UI templates (remember xml-script?), client data sources, accessibility enhancements (make it easy to implement accessibility), animation and drag & drop support, integral client-side components, ASP.NET MVC support as well as several tool enhancements.

Technorati Tags: ,,
Speed Bonnie Boat...

A few things I've learned over the last 10 days or so...

  • Skye is an amazingly beautiful place
  • It's a lot further to the Quiraing than the guidebook suggests
  • It's a lot steeper up to the Old Man of Storr than the guidebook suggests
  • The base of the Old Man of Storr is about the same altitude as the fast jet flypasts - you will get a fright
  • Loch Lomond is the largest loch in Scotland by surface area
  • Loch Morar is the deepest
  • Loch Ness the biggest by volume (in fact Loch Ness contains more water than all the Lakes in England and Wales combined)
  • Loch Ness can be seen from space. I have no idea if this is true - it was postulated by my wife in support of her (incorrect) claim that Loch Ness was longer and wider than Loch Lomond. However, it did lead us to wonder if there's a list somewhere of things that can be seen from space (like, supposedly, the Great Wall) [Update: There is]
  • The Inaccessible Pinnacle is the only Munro that can only be reached by rock climbing (probably putting paid to any chance I have of ever joining the elite group of Munroists)
  • Eilean Donan Castle is gorgeous
  • By my reckoning there are (far) more churches on Skye than there are pubs
  • 1500 miles is an awful long way in an elderly VW camper
  • On a number of occasions I found we were being followed by a breakdown truck and I couldn't help thinking this was in poor taste and somewhat akin to ambulance chasing

DSCF2286

Sadly, the camper van has been sold (on the way back in a service station on the M1 believe it or not) so Skye was her swan song (for us at least).

Technorati Tags: ,,
Another Break in Transmission

Picture1

Yes, crazy though it is, we're setting off tomorrow on a 600+ mile trip to Skye in our 38 year old VW camper. Skye must be one of the most majestically beautiful places on earth yet I've never visited. When we got our camper we promised ourselves a trip up there and the time has come. It's going to be an adventure!

Normal service (if there is such a thing) will resume in about 10 days... If we make it back that is...

Technorati Tags: ,,,
Line Rider on Silverlight

It's funny (almost a little spooky) that only last week I was talking to MikeT about Line Rider and whether we'd ever see a Silverlight version. Then lo and behold I get an email today pointing me to the new Line Rider site in Silverlight 2.

Line Rider is a deceptively simple "game" - draw a line then let loose a little bloke on a sledge to ride it for you. And it's not easy - he falls off and crashes that sledge at any opportunity. This is about the level of sophistication I can muster...

image

But for others it has become what must be almost an obsession. There are videos galore on sharing sites like You Tube and Soapbox...

The Silverlight version has some nice features such as being able to record a movie of your ride and save it online as well as integration with Live Messenger to share tracks with friends etc.

Okay, so it'll probably entertain you for a few minutes (longer if you have kids) but the videos of what others have done with Line Rider are just jaw-dropping.

Technorati Tags: ,,
Adding Dynamic Data to Existing ASP.NET Sites

I posted back in May about the ability to combine standard ASP.NET webforms pages and ASP.NET Dynamic Data pages but I didn't go into the ins and outs of trying to add Dynamic Data capabilities to an existing site. Scott Hunter has two posts on adding the capability to web sites and applications:

He documents the files, references, changes to web.config etc required to make this work.

Technorati Tags: ,
ASP.NET AJAX ScriptReferenceProfiler

I'm not sure how I missed this but we've shipped a ScriptReferenceProfiler control on CodePlex specifically to assist with the new ASP.NET AJAX script combination feature in .NET Fx 3.5 Service Pack 1. In case you're not familiar with the script combination feature, you can now ask ASP.NET AJAX to "aggregate" the scripts required for your page into a single request. This is done with the new <CompositeScript>  element on the <asp:ScriptManager> control. But how to know what scripts are required on your page?

Enter the <asp:ScriptReferenceProfiler>. Drop one of these on your page and it will render the full list of <asp:ScriptManager> scripts required for the page to function. You can then take this list and paste it into the <CompositeScript> element of the <asp:ScriptManager> control. Not only does this ensure you have the minimal set of scripts required to service your page, it also forces them to be combined on the server and served up in a single request via the ScriptResources.axd handler.

Bertrand has made a great 5 min screencast showing all this in action.

Technorati Tags: ,
More Posts Next page »
Page view tracker