Using ITemplate to build EmtpyDataTemplate on GridViews

We're in QA on a .Net project right now, and as QA cycles so often do, this one is flushing out some varying opinions on style. As much as we try to get people to specify this stuff early on, there's nothing like a running system to uncover the closet usability experts.

One of these bugs had to do with the content and style of the message we display when a grid has no data items. I was aware, of course, that the minute I changed it, someone was bound to jump up and ask for the style to be just a little different, so I wanted a solution I could use everywhere, and that would let me change the style when I wanted to.

We'd been using the EmptyDataTemplate in our Gridviews, which would've let me change the style, but wouldn?t let me change the message depending on why the grid had no rows. The EmptyDataTemplate looks something like this:

  <EmptyDataTemplate>
      <asp:Label ID="lblNoData" runat="server">No data found.</asp:Label>
  </EmptyDataTemplate>

Why not use EmptyDataText?  We probably could have made that one work if we?d hard-coded a red font style (bad), or hard-coded a div tag around the text (better, but still not great because we?d have to repeat that all over the place).

So I decided to use a custom template class. I'd never worked with ITemplate before, but I really like it. It reminds me a lot of the stuff that open-source CMS's like PostNuke and Drupal have been doing. I can definitely see using this more in the future. The code for the template class is below, in Listing 1.

To use the template class, set the template based on what's going on (ie, a search). You don't even have to check to see if you have any results - the grid will only display this when there are no rows.

  grdSearchResults.EmptyDataTemplate = 
new NoDataTemplate("No records match your criteria.");

There?s also a parameterless constructor that defaults the message to ?No matching records.?, and another that lets you specify a reason why the results are empty:

grdSearchResults.EmptyDataTemplate = 
new NoDataTemplate(NoDataTemplateReason.NoResultsFound,
"No profiles match your criteria.");

Values for this enum are NoSearchMadeYet, NoResultsFound, and SystemError - default is NoResultsFound. You can mark up styles in your CSS corresponding to these reasons if you want to alter the appearance of any of them:

/* Search results messages when no data present */
.SearchResultsNoSearch 
{ 
    /* no style changes yet, but reserve this spot.  */ 
}
.SearchResultsNoData 
{ 
    /* no style changes yet, but reserve this spot.  */ 
}
.SearchResultsError
{
    color: red;
    font-size: larger;
    font-style: italic;
}

 

Listing 1: NoDataTemplate

 

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public enum NoDataTemplateReason
{
    NoSearchMadeYet,
    NoResultsFound,
    SystemError
}

/// <summary>
///
Summary description for NoDataTemplate
/// </summary>
public class NoDataTemplate : ITemplate
{
    private NoDataTemplateReason reason = NoDataTemplateReason.NoResultsFound;
    private string message = "No matching records.";

    /// <summary>
    /// New template to display when no data present for grid, defaulting Reason to
    /// NoResultsFound, and Message to 'No matching records.'
    /// </summary>
    public NoDataTemplate()
    {
    }

    /// <summary>
    /// New template to display when no data present for grid, defaulting Reason to
    /// NoResultsFound.
    /// </summary>
    /// <param name="Message">Display this message in grid.</param>
    public NoDataTemplate(string Message)
    {
        message = Message;
    }

    /// <summary>
    /// New template to display when no data present for grid.
    /// </summary>
    /// <param name="Reason">What is the reason for no data?</param>
    /// <param name="Message">Display this message in grid.</param>
    public NoDataTemplate(NoDataTemplateReason Reason, string Message)
    {
        reason = Reason;
        message = Message;
    }

    #region ITemplate Members

    public void InstantiateIn(Control container)
    {
        string divText;
        switch (reason)
        {
            case NoDataTemplateReason.NoSearchMadeYet: divText = "SearchResultsNoSearch"; break;
            case NoDataTemplateReason.SystemError: divText = "SearchResultsError"; break;
            default: divText = "SearchResultsNoData"; break;
        }

        Label l = new Label();
        l.Text = "<div class='" + divText + "'>" + message + "</div>";
        container.Controls.Add(l);
    }

    #endregion
}

Where’s the iBill?

I'm crossing over to the dark side. Behold my first iPhone post - but it's not about the phone, it's about the bill.

Justine Ezarik (aka iJustine) has stirred some attention by posting a video unboxing of her first month's iPhone bill from AT&T. It shipped, as she points out, "in ... a ... box." I'll let others handle the tree-hugging, chest-thumping, save-the-environment bit. Instead, I want to tell you a story.

It all started in 1994. A young, energetic, rock-star programmer (modest, too, as it turns out) had just joined a regional long-distance phone company. His charge? To write the next generation of electronic phone bill reporting software. This phone company, you see, sold mainly to businesses, and some of the phone bills got quite large. Cases of paper, large. The electronic call records were provided to the businesses mainly so they could charge LD back to business units and/or employees. Somebody else, apparently, was assigned the responsibility of handing out little lumps of coal to the poor employees.

So the young programmer built the new system, and it was good. It ran on Windows, and it was faster than all of the competing products (it flat smoked AT&T's product, incidentally), and it let users customize the reports. The totals totalled, and the numbers balanced back to the "real" invoice, and people started to ask questions.

"Here I have in my hand a shiny new CD in its easy-to-mail envelope," they began to say, "and there on the floor, in the large cardboard cases, is the invoice. What's up with that?"

So they marched into the conference room and they deliberated. They talked about legalities and customer service. They talked about cost savings and convenience, and they questioned whether anyone who ever received phone bills in cases ever really took the paper out to read any of it. Whiteboards rattled, papers shuffled, gestures were exchanged, and when the doors opened, there was A PLAN. It went something like this:

Customers would be offered the option to receive their invoice in summary form only (cutting the cases of paper down to a few pages), and their call detail electronically. They would introduce this as an option for their largest customers, and expand as it caught on. The stalwart tree-killers couldn't be completely squashed, for they would still mail a summary, but it was a hollow victory. The writing was on the wall, and the age of electronic phone bills was nearly upon them.

That was 1994, folks.

Where are we today? The default phone bill for AT&T is full-detail, printed on paper. There is an option for an electronic bill. That's fifteen years of progress.

I don't lay all of this on AT&T, or any of the other phone companies, for that matter (I happen to know that Sprint & Verizon aren't distinguishing themselves greatly in this area, either). An awful lot of this problem stems from the fact that technology adoption is just a hell of a lot slower than we'd like to think it is.

We live in the technology fast lane. We're always-on, wireless, and connected, but lots of other people aren't. Walk into a bar in St. Louis and ask the first guy you see if he twitters. When you wake up, you'll know what I mean. We take Web 2.0 for granted, but when we make design decisions that impact users, we need to make sure we're not excluding a big hunk of user base as a result.

Back to the iBill. Who really gets the blame for this? Apple. Ol' Steve & the Apple designers. Back in that old phone company, they understood that the most visible, tangible manifestation of "product" was the phone bill. Dialtone was taken for granted - that's what it means to be a utility. The phone bill, though, was the "user interface" for the phone company.

Steve Jobs rocked the UI on the iPhone. I'm not a fanboy, but there's no denying Apple's knack for reinventing the familiar and making us all ask why it wasn't that way in the first place. Sadly, they stopped with the phone and missed the rest of the user interface.

I'm afraid to imagine what we'll have in another fifteen years.

What do Scoble and Yahoo’s President have in common?

They both like Yahoo! stock right now. CNNMoney just reported that Susan Decker bought Yahoo! stock (YHOO) to the tune of about $1m. They note that this buy was "just the fourth by any Yahoo insider in more than four years; and, the largest by any Yahoo insider in more than four years."

Scoble? Well, he's not voting with his dollars like Decker, but he's noticed a change there that could be a sign of better times.

Personally, I wouldn't be surprised if something good happens there. Yahoo's been the subject of a lot of interesting speculation over the last few months. From takeover target to the next great thing in advertising, they're getting a lot of attention. Add to that the fact that they've had their stock beaten down to the point where any good news is going to lift them.

I'm no expert in insider trading law, but I think that if Decker is buying a bunch of stock right now, we can rule out a short-term takeover, so that leaves earning money the old-fashioned way, and that's ok with me. No matter what you think about Yahoo!, they still have a huge audience with an awful lot of page views. It's quite a launching pad for an underdog with a mission.

Thanks. I feel better now…

Here's one I've been meaning to get around to for a while. Marc Andreessen commented on some decisive action from the Governor of Minnesota following last week's tragic bridge collapse:

New York Times home page: The governor of Minnesota and officials from several other states have ordered all bridges to be inspected...

Sadly, this is Standard Operating Procedure whenever there's any sort of calamity on a scale that causes people not to be re-elected. Earlier this year, a whole lot of personal information suddenly went "missing" when a backup tape was stolen out of an intern's car. Yes, you read that right -- an agency of the Great State of Ohio was sending backup tapes home with an intern, and the intern parked his car somewhere with this tape in it, and the tape was stolen. Oops.

So, there's a whole lot of blame to go around on this one, isn't there?

There's the intern, of course. Lots of people have been pretty hard on him, in part because he was actually named pretty early in the unfolding of this debacle. I believe he's now been fired, in fact. Sure, he shouldn't have left this tape in his car.

But seriously, who really expects an intern to be setting and executing policy decisions for identity protection for a state agency? Go read some Dilbert strips with Asok the Intern, and you'll be in a better mindframe to appreciate how ridiculous this is. I've worked with interns before, and I never resorted to making them get me coffee or pick up my dry cleaning, but it wouldn't have been a huge stretch. Interns do what you tell them to do. That's what it means to be an intern.

Meanwhile, the Governor was springing into action, furiously covering his backside and simultaneously searching for someone to hang out to dry. Here's a bit from a press release he tossed out a couple days after this story broke:

The governor has ordered the cessation of this data management practice, a review of the events that led to the data being compromised, and will take appropriate disciplinary action when the facts are known.

The governor has directed by executive order that state information technology managers immediately review, and if necessary change, the procedures for handling back up information to ensure that information is secure at all times.

Whew. That was close. Good thing the Governor stepped up to tell everyone to cease and desist the intern backup rotation. Eerily similar to the Minnesota Governor's release, isn't it?

So am I blaming the Governor for the data theft? No, not really. Ted Strickland just took office in January, and considering the real problems he's got to deal with (like, get an economy), I really would have hoped that he could focus on the big stuff while someone whose business it was to manage data worried about whether backup tapes were sitting in the back seats of cars.

Sadly, the guys in the middle, one or more of whom really *are* responsible in this case, have remained largely anonymous. I've seen a couple articles where various middle administrators have shucked off blame and deflected responsibility, and this is where you find the heart of the problem: a successful career in government (no, not just politics) depends on one's ability to avoid and/or deny any real responsibility for anything, while managing to be involved in everything.

Sound familiar?