Switch On The Code RSS Button - Click to Subscribe
Apr
7

Silverlight DataGrid - The Basics

Silverlight IconI finally downloaded and started using Silverlight 2.0. In a nutshell, it's worlds better than Silverlight 1.0 and 1.1. Of all the new controls we now have access to, the one I was most interested in seeing was the DataGrid. WPF doesn't even have a DataGrid (if you don't count the ListView with a GridView applied), so I surprised when I learned Silverlight was shipping with one. This tutorial is going to introduce you to the DataGrid and demonstrate how to populate it with data from an RSS feed.

I should start this post by commenting on how buggy Silverlight 2.0 currently is. It's still in beta, so I'm not going to say anything bad about it. Keep it mind, however, that you'll probably crash Visual Studio and every one of your browsers before you've completed your first application.

Here's the application we're building today. It contains a DataGrid and a couple of buttons. When the left button is clicked, Silverlight will request our RSS feed and populate the DataGrid with the title and date of each post. When the right button is pressed, the DataGrid will be cleared.

Building the User Interface

The first thing we need to do is get the DataGrid and our buttons onto our Silverlight UserControl. I'm going to assume you know how to get a Silverlight project up and running. Just in case you don't, here's a great 'Hello World' tutorial that should show you everything you need to know.

When you create a new Silverlight project, you're presented with a UserControl and a Grid. I really like Grids for layout, so I'm going to keep it and add my DataGrid as a child.

<UserControl xmlns:my="clr-namespace:System.Windows.Contr..."
             x:Class="BasicDataGridTutorial.Page"
             xmlns="http://schemas.microsoft.com/client/2007"
             xmlns:x="http://schemas.microsoft.com/winfx/200..."
             Width="512"
             Height="350">

  <Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition Height="40" />
    </Grid.RowDefinitions>
    <my:DataGrid x:Name="sotcDataGrid"
                 Grid.Row="0"
                 AutoGenerateColumns="True">

    </my:DataGrid>
  </Grid>
</UserControl>

I added two rows to my layout grid - one to hold the DataGrid and another to hold my buttons. I set the height of the button row to 40 pixels. I then added a DataGrid to my layout. I simply dragged the control from the toolbox, which automatically added the xmlns:my declaration for me. The DataGrid sits in the System.Windows.Controls.Data namespace, so you'll have to remember to bring that into the XAML if you didn't drag and drop the control like I did.

To start out, I set the AutoGenerateColumns property to true to let the DataGrid create and name columns for me. This is a great way to quickly get data on the screen without having to manually set up each column individually, which we'll be doing later in this tutorial.

Next up are the buttons. I simply put these in another layout control called a StackPanel. StackPanels are perfect for creating individual rows or columns of controls.

<UserControl xmlns:my="clr-namespace:System.Windows.Contr..."
             x:Class="BasicDataGridTutorial.Page"
             xmlns="http://schemas.microsoft.com/client/2007"
             xmlns:x="http://schemas.microsoft.com/winfx/200..."
             Width="512"
             Height="350">

  <Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition Height="40" />
    </Grid.RowDefinitions>
    <my:DataGrid x:Name="sotcDataGrid"
                 Grid.Row="0"
                 AutoGenerateColumns="True">

    </my:DataGrid>
    <StackPanel Orientation="Horizontal"
                HorizontalAlignment="Center"
                Grid.Row="1">

      <Button Content="Get SOTC RSS Feed"
              Padding="5"
              Margin="0,0,5,0"
              Height="26"
              x:Name="btnPopulate"
              Click="btnPopulate_Click" />

      <Button Content="Clear DataGrid"
              Padding="5"
              Height="26"
              x:Name="btnClear"
              Click="btnClear_Click" />

    </StackPanel>
  </Grid>
</UserControl>

Requesting the RSS Feed

At this point, you've got something that looks pretty close to the finished product. Now we need to go out and download the RSS feed used to populate the DataGrid. Silverlight 2.0 provides us with a WebClient object that makes this super easy. The WebClient is located in the System.Net namespace.

private void btnPopulate_Click(object sender, RoutedEventArgs e)
{
  //disable the populate button so it's not clicked twice
  //while the data is being requested
  this.btnPopulate.IsEnabled = false;

  //make a new WebClient object
  WebClient client = new WebClient();

  //hook the event that's called when the data is received
  client.DownloadStringCompleted +=
    new DownloadStringCompletedEventHandler(
      client_DownloadStringCompleted);

  //tell the WebClient to download the data asynchronously
  client.DownloadStringAsync(new Uri(
    "http://feeds.feedburner.com/SwitchOnTheCode?format=xml"));
}

I added this code to the click event handler for my btnPopulate button. The first thing I do is disable the button while it's requesting the feed. That way the user can't make another request while one is already happening. It also gives the user a little bit of feedback that something is actually happening while the data is being requested. Next, I make a WebClient object and hook the event that gets fired when the request is finished. Lastly, I instruct the client to request the rss feed asynchronously so the UI can still respond while it's working.

An important piece of information here is that the WebClient can't just request any URL. It can always request a URL on the same domain as the host website, but if the domain is different, the remote server will have to have an XML policy file that gives permission to read the data. Almost all sites that host rss feeds will include this file since they want you to be able to read the rss using other websites and applications.

Populating the Silverlight DataGrid

Now that we've got the data requested, we need to get it into our DataGrid. Fortunately, Silverlight 2 comes with LINQ, which makes parsing XML easier than ever before. If you're new to LINQ, here's one of our introductory tutorials on the subject. The code to fill the DataGrid is going to be added to the event handler for the WebClient's DownloadStringCompleted event.

public class SOTCPost
{
  public string Title { get; set; }
  public string Date { get; set; }
}

...

void client_DownloadStringCompleted(object sender,
  DownloadStringCompletedEventArgs e)
{
  this.btnPopulate.IsEnabled = true;
  if (e.Error == null)
  {
    XDocument document = XDocument.Parse(e.Result);
    var sotcPosts = from post in document.Descendants("item")
                    select new SOTCPost
                    {
                      Title = (string)post.Element("title"),
                      Date = (string)post.Element("pubDate")
                    };

    this.sotcDataGrid.ItemsSource = sotcPosts;
  }
}

Before I started parsing the XML, I needed to create a new object to hold the information about one of our posts. In this case the title and the publish date. I probably would have just bound the DataGrid to the anonymous objects created by the LINQ code, but Michael Sync had a post which indicated that doing this was a known bug in Silverlight 2.0.

The first thing I do in the DownloadStringCompleted event handler is to re-enable the populate button. Next I check to make sure there were no errors in the download process. After that I parse the XML. I'm not going to go into any details on using LINQ since there are already lots of tutorials out there. Lastly, I set the ItemsSource property of the DataGrid to my LINQ output. A DataGrid's ItemsSource property can be set to anything that implements IEnumerable (Array, List, ObservableCollection, etc).

This is where the neat stuff happens. Since we set the AutoGenerateColumns property to True on our DataGrid, it's going to automatically create columns for each property in the SOTCPost object. It will also name them the same as the property's name - Title and Date.

Clearing the DataGrid

When the "Clear DataGrid" button is pressed, we need to remove all the data from the DataGrid. This turns out to be very easy. All we have to do is set the ItemsSource property of the DataGrid to null.

private void btnClear_Click(object sender, RoutedEventArgs e)
{
  this.sotcDataGrid.ItemsSource = null;
}

Customizing the DataGrid Columns

If you noticed the example application at the top of the post, my columns were named something different than my property names. We can accomplish this by disabling the AutoGenerateColumns property and setting up the columns ourselves.

<my:DataGrid x:Name="sotcDataGrid"
             Grid.Row="0">

  <my:DataGrid.Columns>
    <my:DataGridTextBoxColumn
      Header="Post Title"
      DisplayMemberBinding="{Binding Title}" />

    <my:DataGridTextBoxColumn
      Header="Post Date"
      DisplayMemberBinding="{Binding Date}" />

  </my:DataGrid.Columns>
</my:DataGrid>

The Columns property of the DataGrid can be populated with all kinds of different types of columns, but for this example we're going to stick to the basic DataGridTextBoxColumn. The important piece of information here is the DisplayMemberBinding property. This tells the column which property of our object to display in each cell - in this case Title and Date.

Hopefully you found this introduction to Silverlight DataGrids useful and informative. We haven't even begun to scratch the surface of the available features in the DataGrid, but we'll be posting more advanced tutorials in the future. If you have any questions, just leave us a comment and we'll try to answer them as best we can.

References





Posted in Silverlight, All Tutorials by The Reddest |

10 Responses

  1. Fabianv Says:

    “Know thine enemy” hehe. Seriously though, I’d like to give Silverlight a try. Do I have to pay for it?

  2. The Fattest Says:

    No you can download all the Beta bits for free.

  3. The Reddest Says:

    All of the Silverlight SDKs will be distributed free. What does cost money is Visual Studio 2008 Professional, which is currently required if you want to use Visual Studio to write your Silverlight applications.

    In the future, the Express editions of Visual Studio will include Silverlight support, and the Express editions don’t cost anything. The Expression Suite (which is like Flash to Flex) will unfortunately always cost money.

  4. The Fattest Says:

    There is however a beta version of the Expression Suite that you can use to play around with if you’re interested in the design side of Silverlight. Microsoft Expression Studio 2 Beta. You will want the March CTP of Blend though for Silverlight 2 support. Microsoft Expression Blend 2.5 March 2008.

  5. The Fattest Says:

    I also just found out from Scott Guthrie that Microsoft will also support Silverlight development in the free express editions of Visual Studio in the future.

  6. Jason The Saj Says:

    Silverlight = Star Wars Stormtrooper (ie: Clone)

    Man, I must confess, having heard a lot of chatter about Silverlight - I really was NOT expecting it to be such a cop off of Flex.

    It looks like Microsoft MXML + VB Scripting.

    Yes, one day Microsoft will in fact innovate and invent something. Until that day comes, it will continue to do what it does best.

    “Copy, clone, embrace, extend, push…”

  7. The Fattest Says:

    Jason,

    To some extent I agree with your comments. But Silverlight wasn’t built to replicate Flex (it may have been built to compete directly in the space), it was built to bring wpf capabilities to the web. XAML is something Microsoft uses on the desktop and being able to take advantage of .Net skills people already possess is also a plus. Personally I am very much a Flex guy but a lot of the time in the real world companies simply will not move to Flex if they are already a MS shop and Silverlight is available. Not to mention competition at any level is always a plus.

    As for innovation they may not be a bleeding edge of web innovation at the moment but check out projects like XNA and World Wide Telescope. These projects are evidence they too actually do something innovative.

  8. The Reddest Says:

    The XML user interface definition is an architecture that’s been around for a while. Mozilla uses XUL, Google uses it for Android, Microsoft has XAML.

    Flex was one of the first to bring it to the web (if you don’t count HTML/Javascript). Silverlight does look very similar to Flex, but that’s because MXML and XAML look pretty close to every other XML UI definition language out there.

    I believe Flex was a major reason Microsoft decided to create Silverlight, but it looks as thought they are simply transitioning their already existing XAML framework to the web, not creating a new technology by ripping off Flex.

    I totally agree with your last line, though.

  9. Erik Says:

    How can I download the source code to this tutorial?

  10. Frank Says:

    could you update this to the bete 2.2 sdk?

    specifically, how can you undate, with code behine, one of the positions in the grid .. modify what is already there ?

    Thanks

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.

Powered by WP Hashcash