Fans of the open source and highly configurable Eclipse IDE got a present recently: a new beta of the Silverlight plug-in for Eclipse. It offers many of the same features as Silverlight Tools for Visual Studio® 2008, including code-hinting and XAML preview. The plug-in is being developed by Soyatec with funding, architectural guidance, and project management from Microsoft's Interoperability Team. The best way to tour the features of Silverlight for Eclipse is to actually try it. So in this article we'll create a simple Silverlight app using Eclipse—a syndication feed reader. The app lists feed items in the top of the window, and displays the selected feed item beneath the list. It's amazing how little code it takes to put this together. Here's what the finished app looks like:
![]() | |
| Figure 1. Syndication Feed Reader |
Install the Silverlight Development Toolkit
The Silverlight module requires the following software, installed in the order shown:
A few things to note with this beta:
After you install Silverlight, you should update to the December 2008 release of the DataGrid, which fixes nearly 30 bugs. We'll be using the DataGrid in our tutorial.
Once you've installed all the prerequisites, you are ready to install the Silverlight plug-in. Launch Eclipse, then select Help->Software Updates to open the Software Updates and Add-ons dialog. Select the Available Software tab and click the Add Site… button.
![]() | |
| Figure 2. Select the Available Software tab and click the Add Site… button. |
In the resulting dialog box, type http://www.eclipse4sl.org/update/ and click OK. Don't leave off the "www". If you do, you'll get an annoying duplicate entry that doesn't hurt anything but looks ugly.
![]() | |
| Figure 3. Type http://www.eclipse4sl.org/update/ and click OK. |
Now there will be a new entry on the Available Software tab for Silverlight. Select the Silverlight entry, then click the Install… button. Eclipse will install the Silverlight plug-in and all its dependencies.
![]() | |
| Figure 4. Select the Silverlight entry, then click the Install… button. |
To see exactly what it installed, select Help | About. The plug-in button with the cube icon is for Silverlight.
![]() | |
| Figure 5. The plug-in button with the cube icon is for Silverlight. |
Click the cube icon to bring up the Silverlight module information dialog:
![]() | |
| Figure 6. Click the cube icon to bring up the Silverlight module information dialog. |
Then click the Plug-in Details button to see all the components:
![]() | |
| Figure 7. Click the Plug-in Details button to see all the components. |
Create the Project Template
Now we're ready to build our Silverlight app. To start, select Windows->Open Perspective->Other… to open the perspective selection dialog:
![]() | |
| Figure 8. Select Windows->Open Perspective->Other… to open the perspective selection dialog. |
Notice that Silverlight is listed twice. The first entry, with the little blue cube, is the Eclipse-style perspective with the Project Explorer docked on the left and the palette docked on the right. The second entry is the Visual Studio style perspective, which reverses these.
Now that the Silverlight perspective is set, select File->New. You'll see two types of Silverlight projects to choose from: Silverlight Project and Silverlight Web Project. Select Silverlight Web Project. This lets you embed your Silverlight app within a Web page that has other elements.
![]() | |
| Figure 9. A Silverlight Web Project lets you embed your Silverlight app within a Web page that has other elements. |
Next you'll see the New Project dialog. Enter SyndicationFeedReader as the project name. This project doesn't depend on any other projects so you don't have to click Next. Just click Finish:
![]() | |
| Figure 10. In the New Project dialog, enter SyndicationFeedReader as the project name. |
Before we go any further, let's see what was created for us. Project Explorer shows two projects: SyndicationFeedReader and SyndicationFeedReader.Web:
![]() | |
| Figure 11. Project Explorer shows two projects: SyndicationFeedReader.Web and SyndicationFeedReader. |
In the screenshot above, the mouse cursor is hovering over the View Menu button. The View Menu doesn't display in the current version of the plug-in, but you can open and close your Silverlight projects from other Eclipse perspectives.
Let's build and run what we have so far. It will display only a blank page, but it gives us a chance to set things up. Select Run->Run configurations… to bring up the Run Configurations dialog. Select Silverlight Web App from the list, and then click the New button:
![]() | |
| Figure 12. Select Run->Run configurations… to bring up the Run Configurations dialog. |
Next you'll see the configuration dialog. In the Name field enter SyndicationFeedReader, and for Project to test select SyndicationFeedReader.Web. The start page, SyndicateFeedReaderTestPage.html will be selected. Click Apply and then Run:
![]() | |
| Figure 13. Enter the run configuration name and select the project start page. |
This will launch what appears to be a blank page in your browser but if you right-click in the browser window, you'll see the Silverlight Configuration context menu. Silverlight is running—there's just nothing there yet.
Note: We will need to make some small changes in SyndicationFeedReaderTestPage.html, but it may not be listed as part of the SyndicationFeedReader.Web project in Project Explorer. (Soyatec has fixed this bug, but the fix may not be released by the time you read this.) If it's missing, here's how to add it. Right-click on the project name SyndicationFeedReader.Web and select New -> Add existing file. Then navigate to the project directory, change the filter to *.*, and select the file. You'll be asked if you want to overwrite the existing file. Say no. The file will appear in your project list.
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:
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.