RIA Development Center
FeaturesTipsEventsVideosSilverlight GallerySilverlight Hosting Resources
Which platform do you use most often?
(Check one)
AIR
AJAX
Flash
JavaFX
Silverlight
Other

View Results
Get regular email alerts when we publish new features!
DevX RIA Development Update

More Newsletters
Getting Started with Silverlight for Eclipse (cont'd)

Customize the Code for Our App
Now let's create the user interface by adding code to Page.xaml. XAML (pronounced "zammel") stands for eXtensible Application Markup Language. XAML files are a type of XML. Double-click Page.xaml to open it in the editor. The lower pane holds your source code, and the top pane gives a preview of what it will look like.

You'll see the file already contains some skeleton code. The top-level UserControl element wraps all the Silverlight content on the page. We'll start by removing the Width and Height parameters. This allows the Silverlight content to expand to fill the browser window. Next change the Background color from White to Purple:

<UserControl x:Class="SyndicationFeedReader.Page"
    Xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation 
    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 
    >
    
    <Grid x:Name="LayoutRoot" Background="Purple">

    </Grid>

</UserControl>

The Silverlight Grid control works much like an HTML table, though the syntax is different. Our Silverlight app will contain two rows. The top row will hold a label and a button for accessing the feed items. The bottom row will contain the list of feed items. The display of the selected feed item will be done in HTML, below the embedded Silverlight app.

To add row definitions, use this syntax:

<UserControl x:Class="SyndicationFeedReader.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    >
    
    <Grid x:Name="LayoutRoot" Background="Purple">

        <Grid.RowDefinitions>
            <RowDefinition Height="70" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

    </Grid>
    
</UserControl>

Next we want to add a horizontal StackPanel to hold the label text and the button. The Palette on the right can help. Click on Containers, then drag the StackPanel item to the code window below the row definitions but still inside the grid. Insert your cursor at the end of the <StackPanel> tag, type a space, and then press Ctrl+Space to bring up code hinting. Scroll down until you reach Orientation (or type "O" to speed your search) and double-click to select it. The default value of "Horizontal" is what we want.

Our two StackPanel controls will be a TextBlock and a Button. The TextBlock will simply say "Wired" (the name of the feed we are using in this tutorial). Note that not all feeds will work. The domain must permit cross-domain access by hosting a small file on the server such as this one on wired.com.

To add a TextBlock, click Controls in the Palette, then drag the TextBlock item to your source code window, between the StackPanel tags. Then click on Button and drag a Button control to the source window below the TextBlock. Configure the controls as shown below. We don't have to tell it to use the first line of the grid (row 0) because it does this by default. As with the StackPanel, you can get syntax help by pressing Ctrl+Space.


       <StackPanel Orientation="Horizontal">
			
            <TextBlock Text="Wired" 
                VerticalAlignment="Center" 
                FontSize="36" 
                Padding="10"
                Foreground="White" 
                />

            <Button Content="Get Feed"
                Margin="5"
                Height="50"
                Width="100"
                Foreground="Purple"
                />

	</StackPanel>

So far so good, but the button doesn't do anything yet. We need to add an event handler so that clicking on the button accesses the feed. Position your cursor before the button's closing bracket and press Ctrl+Space. One of the options in the code hint box is the Click event. Double-click on this to select, and an event handler dialog will appear. Type in Btn_Click as the event name, and click OK:

Figure 14. Select the Click event from the code hint box and an event handler dialog will appear.

This will then create an event handler stub in the code-behind file, Page.xaml.cs, and open it for editing. The event handler needs just three lines of code.

First we instantiate a WebClient object for accessing server data. Then, since we will access the feed asynchronously, we need to add an event handler for the OpenReadCompleted event. And finally, we use the OpenReadAsync method to submit the request for the feed:


        private void Btn_Click(object sender, RoutedEventArgs arg1)
        {
            WebClient client = new WebClient();
            client.OpenReadCompleted += 
                  new OpenReadCompletedEventHandler(client_OpenReadCompleted);
            client.OpenReadAsync(
                  new Uri("http://feeds.wired.com/wired/index?format=xml"));        
        }

The OpenReadCompleted event handler will bind the feed data to the control that displays it—in our case, the DataGrid control. So before we add the handler, let's go back to Page.xaml and add the DataGrid.

Click Containers in the Palette, drag the DataGrid item to your source window, and drop it beneath the StackPanel (between the two close tags </StackPanel> and </Grid>). This not only adds the DataGrid tags to your source code, it adds the additional namespace to the top of the file, and adds a reference to System.Windows.Controls.Data to your project.

We want to give our DataGrid a name so we can refer to it in the OpenReadCompleted event handler, where we will bind the feed data to it. Give it the name gridSyndicationItems, and then add two more attributes: Grid.Row="1" (since the list goes in the second row of the grid—the first is row 0) and AutoGenerateColumns="false" (more on this in a minute). Finally, we want our Web page to display the selected feed, so we need an event handler for SelectionChanged. Code hinting can help with all of these; just press Ctrl+Space.

If you don't set AutoGenerateColumns to false, the DataGrid will automatically generate a column for every field in the feed, and generally you're not going to want that. If you set it to false, you can then define which columns to display, which is what we want to do. This is what the DataGrid markup should look like when you're done:


    <Controls:DataGrid x:Name="gridSyndicationItems" Grid.Row="1"
          AutoGenerateColumns="false" SelectionChanged="gridFeed_SelectionChanged" >
			
           <Controls:DataGrid.Columns>
                     <Controls:DataGridTextColumn Binding="{Binding Title.Text}" />
                     <Controls:DataGridTextColumn Binding="{Binding PublishDate}" />
                     <Controls:DataGridTextColumn Binding="{Binding Id}" />			
            </Controls:DataGrid.Columns>
			
    </Controls:DataGrid>

The Binding statements specify what fields to display in each column. The field names are properties of the Syndication Field object.

Now let's go back to our code-behind file, Page.xaml.cs, and add the event handler for when the feed reading has completed. Type the code for the OpenReadCompleted handler right below the Btn_Click handler:

         private void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
         {
            if (e.Error == null)
            {
                XmlReader reader = XmlReader.Create(e.Result);
                SyndicationFeed feed = SyndicationFeed.Load(reader);
                gridSyndicationItems.ItemsSource = feed.Items;
                reader.Close();
            }
          }

If there are no errors in getting the feed, we create a new instance of the XmlReader object and initialize it with our feed. Then we load the XML reader into a SyndicationFeed object called "feed" whose Items property contains the collection of feed items. To bind the feed data to the DataGrid, we assign feed.Items to the ItemsSource property of the DataGrid.

One thing, though. The namespace that contains the SyndicationFeed class is not yet a part of our project. In Project Explorer, expand the SyndicationFeedReader project, right-click on References, and select Add Reference:

Figure 15. Right-click on References in the SyndicationFeedReader project and select Add Reference.

This brings up a list of available assemblies, with those currently part of the project highlighted in grey. Select System.ServiceModel.Syndication and click OK:

Figure 16. Select System.ServiceModel.Syndication and click OK.

Now we need to add a few "using" directives to our code-behind file, Page.xaml.cs:

using System.ServiceModel.Syndication;
using System.Xml;
using System.Windows.Browser; 

System.Xml and System.Windows.Browser are used in displaying the selected feed item. There are two parts to this:

  • An event handler for when the selected feed item has changed.
  • HTML to display the selected feed item in an iframe on the page.

Add the SelectionChanged event handler below the OpenReadCompleted event handler. This time the stub isn't created for us (code hinting will be enhanced in future versions):


        private void gridFeed_SelectionChanged(object sender, EventArgs e)
        {
            SyndicationItem selectedItem = 
                  (SyndicationItem)gridSyndicationItems.SelectedItem;
            HtmlElement element = 
                   HtmlPage.Document.GetElementById("rssFrame");
            element.SetAttribute("src", selectedItem.Links[0].Uri.ToString());
        }

The first line updates the selected item, and the next two lines allow it to be displayed. Notice the reference to "rssFrame". This is name of the iframe that will hold the display.

The last step is to add the iframe to our HTML page. Right click on SyndicationFeedReaderTestPage.html in the SyndicationFeedReader.Web project, and select Open With->Text Editor. First, limit the embedded Silverlight app to 50 percent of the page by changing the height of the silverlightControlHost from 100 percent to 50 percent:


    #silverlightControlHost {
	    height: 50%;
    }

Then add these two lines just before the </body> tag:

     <hr style="color: Purple; height: 20px;" />
     <iframe id="rssFrame" width="98.5%" height="50%" />

That's it! Save everything, and then go to the Run menu and select Run History->SyndicationFeedReader. When the browser window with the app is launched, click the Get Feed button to load the feed items. As you select different items, the associated page will load in the bottom half of the window. You can run the app outside of Eclipse by double-clicking SyndicationFeedReaderTestPage.html.

Interoperability with Java Web Services
We've built a very simple demonstration app here, but the Silverlight plug-in for Eclipse is not limited to creating standalone Silverlight applications. It also supports interoperability with Java Web services based on SOAP or REST protocols. You can find details and sample code online.

The Silverlight project for Eclipse is in active development. Your feature requests and feedback are welcome.

* This article was commissioned by and prepared for Microsoft Corporation. This document is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.


Previous Page: Create the Project Template  
Sheryl Canter is a technophile and developer for Windows and the Web. She's written extensively about computers and technology for PC Magazine and other publications, and for 10 years was editor of PC Magazine's popular Utilities column. Her Web site and blog are at www.SherylCanter.com.
Page 1: Getting StartedPage 3: Customize the Code for Our App
Page 2: Create the Project Template 
Rate This Content:
Low     High
4 after 4 ratings