Archive for Silverlight

Connecting Drupal and Silverlight: By Matt Serbinski

Note: This article is submitted by Matt Serbinski for Silverlight 2 Beta 2 - Articles Competition.Thanks a lot, Matt! Hello All, Please drop a comment if you like it.

Connecting Drupal and Silverlight
Connecting Drupal and Silverlight

Contents

  • Introduction
  • Custom Module for Drupal
  • Silverlight application
  • About the Author (Matt Serbinski)

Download ~

Introduction

Drupal is an open source content management system (CMS) that allows users to add modules to their sites for great flexibility. These modules are typically written in PHP and use drupal’s API to connect themselves with the framework. Silverlight (version 2.0 and greater) is a cross-platform browser plugin that allows users to write managed .NET code for the back end and use XAML as the front end. Since silverlight is a browser application and drupal is a framework for hosting data in browsers there can be data that is shared between the two using HTTP as the transport. In this example, I have chosen to use XML-RPC as drupal uses xml-rpc natively and silverlight can easily take advantage of this.

XmlRPC
XmlRPC

One thing to note, drupal has a module called services that is currently under development that will allow external applications (such as silverlight) to easily communicate through various interfaces, such as: XML-RPC, SOAP, REST and AMF. I am NOT using this module in my example.

Custom Module for Drupal:

As far as the drupal side of things go, I have a basic install of drupal 6.2 with a custom module that I have written to communicate with my silverlight application. I wrote the module based off of tips from Pro Drupal Development using chapters 2 and 19. There are two files that are needed to construct a drupal module: a .info file that contains information about the module and a .module file that is the actual custom module. My custom module is extremely simple in which it implements hook_xmlrpc to map xml-rpc methods to php callback functions. The xml-rpc methods are received from silverlight and then call the appropriate php function with the appropriate arguments. My php functions do various tasks, such as: checking the drupal database to see if a user exists so that user can login if the correct credentials are supplied,logging in an anonymous user, logging a user out and creating a fully authenticated user. Once the module is uploaded to the server, enable the module and your done! Well, done with the drupal side.

Silverlight application

There are currently two methods in silverlight to communicate via a web service (in this case xml-rpc): WebClient and HttpWebRequest. HttpWebRequest contains all of the properties and methods that WebClient has and then some. But of course the extra goodies that HttpWebRequest provides come at a price; added complexity. WebClient is extremely easy to use and only requires one event and one property to be used, all though there are additional events and properties that can make life easier. Here are the events and properties that I have used in my application:


drupalDB = new WebClient();
drupalDB.UploadStringCompleted += new UploadStringCompletedEventHandler(drupalDB_UploadStringCompleted);
drupalDB.UploadProgressChanged += new UploadProgressChangedEventHandler(drupalDB_UploadProgressChanged);
drupalDB.UploadStringAsync(location, xmlData);

drupalDB is my WebClient and there are two events defined that will notify me when upload progress has changed (perfect for a progress bar) and completed. The property, UploadStringAsync takes in a Uri and a string as the data to upload to the web service. One thing to note here is that I am using UploadStringCompleted and not DownloadStringCompleted as WebClient does a GET for downloads and a POST for uploads and xml-rpc only accepts POSTs.

The data that I am uploading to the xml-rpc service is a string that is xml formatted that uses the standard xml-rpc definition:

</p></p>

string xmlData = "<?xml version=\"1.0\"?>"
+ "<methodCall>"
+ "<methodName>userlogin.logAnonIn</methodName>"
+ "<params>"
+ "<param>"
+ "<value>"
+ "</value>"
+ "</param>"
+ "</params>"
+ "</methodCall>";

There are two important things to note here. The tag <methodName> contains the xml-rpc method that the hook_xmlrpc function will map to a php function. The first part of that argument, userlogin is the name of my module and a standard format that drupal follows. The <param> tag contains a <value> tag where an argument can be passed to the hook_xmlrpc function. If multiple arguments are required then one needs to add additional <param><value>my data here</value></param> tags in between the <params> tag. Once the data is sent from silverlight to drupal and the appropiate mapping php function is processed, a return value is sent back to silverlight:


<methodResponse>
<params>
<param>
<value>
<string>return value</string>
</value>
</param>
</params>
</methodResponse>

The UploadStringCompleted event will fire once all of the above data is received. A popular way to parse the returned data is to use LINQ. LINQ is very powerful and very easy to use once you learn a little about it. I can parse the above data with the following LINQ statement:

</p></p>

XDocument document = XDocument.Parse(e.Result);
List<MethodToCall> methodsToCall = (from user in document.Descendants("value").Elements("string")
select new MethodToCall
{
MethodName = user.Value
}).ToList();

I place the result in an XDocument and use LINQ to parse the document for any node ‘value’ that has a child node ’string’. This is the standard format that xml-rpc sends. If there are mutliple arguments then there will be multiple ‘value’ nodes. I call ToList() on the LINQ statement to create a generic list for multiple arguments that may be passed back.

With my particular application, since I can control what I send to and from the xml-rpc service, I decided to use reflection and pass back a string from drupal that I have defined as a method in my silverlight application. One thing to note here is that arguments are passed back as objects. If multiple arguments are passed back they are each an object, not an object[] so your method must take multiple arguments that are each objects instead of one argument of type object[].

After my method is called via reflection I simply update my user object as appropriate. And that’s it! That is the basics of how to get drupal to talk to silverlight and vice versa. Of course, one needs to add some more logic and flare to a silverlight application to take advantage of the data it receives from drupal. I have added a few items that hopefully make the user experience that much better (and easier) in my user login application.

As a side note, once silverlight is configured on your web server all you need to display the silverlight application is the following html code placed wherever you would like:

</p></p>

<div style="width: 325px; height: 350px;">
<object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">
<param name="source" value="/silverlight/SLApps/DrupalGameDemo.xap" />

<!-- Only need the below to show a link to get silverlight if it is not installed -->
<a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none" />
</a>
</object>
</div>

The <object> tag contains a <param> tag that has the ‘value’ attribute of the location of your .xap file. The link in the above html code (<a> tag) is the link that will be displayed if a user does not have silverlight installed.

Feel free to try out the attached silverlight application (it is also displayed at the top of this page) and change things to your liking. Enjoy!

About the Author (Matt Serbinski)

My name is Matt Serbinski and I graduated from Rochester Institute of Technology (RIT) in March 2007 with a BS in computer engineering. I have been working at my current job, Naval Surface Warfare Center in Dahlgren, Virginia since 2004 while I was cooping. I have worked on a handful of projects that integrate existing technologies (lethal and non lethal) onto vehicle platforms as a single point to control everything. I was introduced to WPF when it was in beta and started to love everything it offered. Once Silverlight 2.0 was in beta I started to develop applications on the side for fun. I enjoy taking technologies and figuring out ways to use them together and developing WPF and Silverlight applications for fun.

VIEWS - Opensource Virtual Earth Wrapper for Silverlight

Jared Bienz from Microsoft announced that VIEWS, the Virtual Earth Wrapper for Silverlight, is live on Codeplex.

VIEWs is a wrapper around the JavaScript Virtual Earth control that allows a developer to write a complex Virtual Earth Mashup using a managed language for all client-side scripting. It was originally created by Adam Eversole in Microsoft Research and it was an internal-only project when Jared found it. Then,  Jared refine and polish it with the help of Adam within 8 days. Now, we all can download the VIEWS and its sample project. If you are new to VIEWS, you can take a look at Jared’s screencast and Getting Start tutorial.

(Yes. He announced about that July 1 but there was a few issues in accessing the homepage of VIEWS in Codeplex. Now, I just checked the URL agan and found that we are able to access the home page of VIEWS so I’m posting about that information here. )

Tall skinny data columns using improved WrapPanel for Silverlight: By Matt Perdeck

Note: This article is submitted by Matt for Silverlight 2 Beta 2 - Articles Competition.Thanks a lot, Matt! Hello All, Please drop a comment if you like it.

Download: TallColumns.zip (758 KB)

Contents

Introduction

When it comes to presenting data, there is a lot of emphasis on grids that present data in a single wide column, showing lots of fields horizontally.

However, some data tend to be presented in narrow columns, such as address lists and book indices. Instead of complex navigation, they have letter buttons, so you can quickly get to everybody whose name starts with “K”.

And, now that lots of people use monitors that are much wider then they are high, it makes sense to put the column into a vertical WrapPanel, so it takes all the available monitor width. Less scrolling and less wasted screen real estate.

The solution I came up with has a nice (I think) page transition effect. It supports paging at the data level, to minimize network traffic. Although people have already come up with WrapPanel implementations for Silverlight, I decided to do an improved version for this project (details). I also did a very simple reusable GroupHeader element that makes it easy to insert group headers in the list of records (the red “A”, “B”, etc., you see in the image above).

Requirements

Installation

  1. Download the zip file with the source code, and unzip in a directory.
  2. Open the TallColumns.sln file in Visual Studio.
  3. The main project within the solution is TallColumns. Project TallColumns2 is a version of TallColumns that uses scroll bars. The other projects are described further below.

How to add the GroupHeader element and the improved WrapPanel to the toolbox

  1. Build the solution.
  2. Right click in the toolbox and choose “Choose Items”. This opens the “Choose Toolbox Items” window.
  3. Click the Silverlight tab.
  4. Click the Browse button, and double click the WrapPanel.dll in the WrapPanel/Bin directory.
  5. Now, do the same with the GroupHeader.dll in the GroupHeader/Bin directory.
  6. Click OK to add the controls to the toolbox.

TallColumns Project

If you download the source file and open the solution, you’ll find it contains a number of projects.

The TallColumns and TallColumns2 projects contain the actual XAML. TallColumns2 is the same as TallColumns, except that it uses a ScrollViewer to show that the WrapPanel used here can be used with a ScrollViewer.

By way of test data, a list of companies and their addresses is used.

Page.xaml

The Page.xaml file starts with the two Storyboards that create the page transition effect when you move from page to page with the “Next” button, “Previous” button, etc. One blurs the page, and the other makes it visible again. The code actually updates the page contents after the first storyboard has completed but before starting the second storyboard.

After the storyboard definitions comes a horizontal StackPanel with the navigation buttons. The letter buttons sit in their own ItemsControl. The letters are actually loaded from the same database object as the main records. That makes it easy to ensure that if there are no companies starting with “X”, there is no “X” button either.

Finally, there is the ItemsControl that shows the actual company records. If you look at its ItemTemplate, you’ll see that on top of the TextBlocks for the record fields is a GroupHeader element that at the appropriate time shows the first letter of the company name (how this works). The ItemsControl’s ItemsPanel meanwhile specifies that a WrapPanel is being used to show the records (details WrapPanel).

Page.xaml.cs

When you look at Page.xaml.cs, you’ll find that all the code that makes the tall columns work is in a separate class TallColumnsManager, defined in the project TallColumnsManager. This to facilitate code reuse.

TallColumnsManager project

The TallColumnsManager class contains all the code needed to manage tall columns. When you look in the TallColumnsManager.cs file, you’ll see it is extensively documented.

Db Project

This project acts as the Data Access Layer. It has the Customer class that defines a customer, with company name, address, etc. The CustomerGroupCaption class defines the letters for the letter buttons. And, the CustomerAccess class exposes the methods used by the TallColumnsManager object (passed in via delegate parameters to the TallColumnsManager constructor) to retrieve the data. The methods are well documented in the source file.

Obviously, this project is just a dummy, with the data hard coded (old timers will recognize the Northwind list of customers). However, it would be easy to change the implementation so it retrieves data over the network, minimizing traffic by only retrieving a page load of records instead of all available records. This wouldn’t affect the class’ interface or the rest of the tall columns code.

WrapPanel Project

Improvements

This WrapPanel has a few improvements compared with the WrapPanel published by lneir:

  • Can be used inside a ScrollViewer.
  • Allows you to only show complete child elements (leaving out elements at the edges that are partly cutoff).
  • Lets you get the number of elements shown within the WrapPanel. This is useful when you try to create a paged interface with elements of different sizes.

WrapPanel Members

WrapPanel derives from Panel. It adds the following methods and properties to those provided by Panel:

Methods


static WrapPanel GetWrapPanel(string name)

Given the name of a WrapPanel, returns a reference to that WrapPanel. This may be the only way to get a reference to a WrapPanel that is used as the ItemsPanel of an ItemsControl.

Example:


WrapPanel wp = WrapPanel.GetWrapPanel("MainWrapPanel");

Properties

Name Type Description
Orientation Orientation Either Orientation.Horizontal or Orientation.Vertical.
ShowIncompleteChildren bool If true, you may see incomplete child elements at the right or bottom edge of the WrapPanel.

If false, child elements that cannot be completely shown within the WrapPanel are not shown at all.

ShownChildren int Number of child elements currently shown in the WrapPanel. Only valid after the WrapPanel has loaded (Loaded event has fired).

GroupHeader Project

This is a very simple element that makes it easy to insert single letter group headers in the list of records shown with an ItemsControl.

Say, you are showing the company name and address of a list of companies, sorted by company name, in an ItemsControl:


<ItemsControl  ...>
<ItemsControl.ItemTemplate>

<DataTemplate>
<StackPanel Orientation="Vertical" >
<TextBlock FontWeight="Bold" Text="{Binding CompanyName}" />

<TextBlock Text="{Binding Address}" />
</StackPanel>
</DataTemplate>

</ItemsControl.ItemTemplate>
</ItemsControl>

With the GroupHeader element, you can then insert a TextBlock each time a company name starting with a new letter is reached. The TextBlock would show that letter, like this:

A
Alfreds Futterkiste
Ana Trujillo Emparedados y helados
Antonio Moreno Taquería

B
Berglunds snabbköp
Blauer See Delikatessen
...

The GroupHeader element goes above the TextBlocks with the actual record fields:


<ItemsControl  .....>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" >

<my:GroupHeader GroupName="Main" GroupingValue="{Binding CompanyName}">
<my:GroupHeader.Template>
<ControlTemplate TargetType="my:GroupHeader">

<TextBlock x:Name="GroupHeaderText"></TextBlock>
</ControlTemplate>
</my:GroupHeader.Template>

</my:GroupHeader>
<TextBlock FontWeight="Bold" Text="{Binding CompanyName}" />

<TextBlock Text="{Binding Address}" />
</StackPanel>
</DataTemplate>

</ItemsControl.ItemTemplate>
</ItemsControl>

The GroupHeader has a template containing the TextBlock that will show the letter. Add properties to make it bold, change its color, etc.

Make sure that the TextBlock in the template has the name “GroupHeaderText“.

Instead of a TextBlock, you can also use a Button or HyperlinkButton, like this:


<my:GroupHeader GroupName="Main" GroupingValue="{Binding CompanyName}">
<my:GroupHeader.Template>
<ControlTemplate TargetType="my:GroupHeader">

<Button x:Name="GroupHeaderText" Click="LetterButton_Click"></Button>
</ControlTemplate>

</my:GroupHeader.Template>
</my:GroupHeader>

Bind the GroupingValue property of the GroupHeader to the record field whose first letter the GroupHeader needs to look at (CompanyName, in this case).

If you have more then one ItemsControl with a GroupHeader in your application, assign a unique name to the GroupName property of each GroupHeader.

When you reload an ItemsControl with a GroupHeader (for example, by assigning a new collection of records to the DataContext of the ItemsControl), use the static GroupHeader.ResetGroup(string groupName) method to reset the group. That way, the last record processed before the reload doesn’t upset the group headers after the reload.

For example:


// Reset group before assigning new collection to the ItemsControl
GroupHeader.ResetGroup("Main");
MainItemsControl.DataContext = newCollection;

About the Author (Matt Perdeck)

  • Technical skills used in last 2 years: AJAX, JavaScript (5 years), ASP.NET 3.5 and 2.0 (C#, VB.NET), SQL Server 2000 and 2005, XML, XHTML, CSS, InsiteCreation CMS.
  • Other technical skills include: Visual C++ (5 years), PHP, C, Linux, HTTP, SMTP, POP3, TCP/IP, PERL, C, embedded low level multi tasking software, CGI, MySQL, X.25, SNA.
  • Loves developing software. Passionate about producing reliable and maintainable software that makes the client happy.
  • Ranked #4,369 out of 154,356 (top 3%) at rentacoder.com.
  • GMAT score in top 2%.
  • Graduated with BSc Computer Science in 1987 from University of Technology Twente, The Netherlands.
  • Dutch national, with Australian permanent residence. Has worked in The Netherlands, Australia, Slovakia and Thailand.
  • Currently on contract with a major international publishing house until 1 August 2008, developing web sites.

    Email: mperdeck (at) gmail (dot) com
    Web site: http://advancedwebsitetechnology.com

Silverlight Drag, Drop, Import , and Export: By Michael Washington

Note: This article is submitted by Michael for Silverlight 2 Beta 2 - Articles Competition.Thanks a lot, Michael!
Hello All, I would like to remind you that our contest will be closed on 25th July, 2008 so please get writing and submit your great article as soon as possible. You will get a chance to win cool prizes. Your articles will be read by a lot of Silverlight fans and you will be recognized by our Silverlight community. Plus, we will drive some traffic to your site. This contest is sponsored by SilverlightShow.net and Silverlight 2 in Action.

Contents

  • Silverlight Drag, Drop, Import , and Export
  • The Code
  • Creating the Windows
  • The ImportContent Method
  • Summary
  • Author Bio

Download ~

SourceCode: SilverlightDragDropImportAndExport.zip (618 KB)
Live Demo : Silverlight Drag and Drop/Import and Export Demo

Silverlight Drag, Drop, Import , and Export

The example is based on an earlier drag and drop code sample that was based on an example created by Keith Mahoney. In his example he shows how to drag and drop various types of elements into various types of Panels. In this example we only cover dragging and dropping an element onto a Canvas. We also cover importing and exporting content from one user control into another.

When you view the sample you see three movable windows (you grab the colored bar on the top of the window to drag it) with three boxes in the first window.

The “Drag Me” box can only be dragged inside the window, but the blank box and the “Drag Me Outside” box can be dragged anywhere on the screen.

To determine the different behavior of the boxes, the word “[draggable]” is added to the Tag property of the element that will be draggable outside the window. When an element with that Tag is detected, the element is removed from the Canvas it is currently on and placed on the root Canvas of the application while it is being dragged.

When the element is dropped a HitTest is performed to see if the mouse is currently in the bounds of a Canvas element that is in one of the windows. If it is in the bounds, the element is removed from the root Canvas and placed onto the Canvas that is in the respective window.

If the boxes are dragged inside another window, they will remain in the window and move with that window when that window is moved.

The window labeled “Drop Items Here” implements a “ImportContent” interface that allows content to be possibly imported and parsed rather than simply added to the window. When the blank box is dragged onto the window labeled “Drop Items Here”, the box is simply added to the window.

However, when the box labeled “Drag Me Outside and Export Me” is dragged onto the window labeled “Drop Items Here”, the TextBlocks in the box are parsed and their content is added to the TextBlock in the window.

The Code

The solution file contains a Silverlight project and a web project to display the Silverlight project output. The following describes the files in the SilverlightDragAndDrop project:

  • Page.xaml - This is the main control that is displayed by the web project. This control creates windows using the SilverlightWindowControl control and inserts the contents of the SilverlightCanvas controls. It also create handlers to handle the drag and drop of the elements and calls the ImportContent method if it exists on the panel an element is being dropped on.
  • SilverlightCanvas1.xaml -  This control implements an ImportContent interface and a TextBox to display any imported content.
  • SilverlightCanvas2.xaml -  This control simply contains a blank Canvas that elements can be placed on.
  • SilverlightObjects.xaml -  This control contains three elements that can be dragged and dropped.
  • SilverlightWindowControl.xaml - This control is used by the Page.xaml control to create the windows the other controls are placed into.
  • Interfaces.cs - This contains an interface called ImportContent that the SilverlightCanvas1.xaml control implements to import content.

Creating the Windows

The Page.xaml control creates the three windows and a list of panels that elements can possibly be dragged onto. It will perform a HitTest to determine if an element is being dragged onto one of the panels.


public Page()
{
InitializeComponent();

// Window #1 - Contains objects
SilverlightWindowControl objSilverlightWindowControl = new SilverlightWindowControl(50);
// Pass an instance of this control to the child control. This will allow the child to
// wire-up mouse events to the parent.
SilverlightObjects SilverlightObjects = new SilverlightObjects(this);
objSilverlightWindowControl.Window.Content = SilverlightObjects;
Canvas.SetLeft(objSilverlightWindowControl, (double)50);
Canvas.SetTop(objSilverlightWindowControl, (double)50);

// SilverlightCanvas1 - Implements the "ImportContent" Interface
SilverlightWindowControl objBlankSilverlightWindowControl1 = new SilverlightWindowControl(60);
SilverlightCanvas1 objSilverlightCanvas1 = new SilverlightCanvas1();
objBlankSilverlightWindowControl1.Window.Content = objSilverlightCanvas1;
Canvas.SetLeft(objBlankSilverlightWindowControl1, (double)300);
Canvas.SetTop(objBlankSilverlightWindowControl1, (double)50);

// SilverlightCanvas2 - Does NOT implement the "ImportContent" Interface
SilverlightWindowControl objBlankSilverlightWindowControl2 = new SilverlightWindowControl(60);
SilverlightCanvas2 objSilverlightCanvas2 = new SilverlightCanvas2();
objBlankSilverlightWindowControl2.Window.Content = objSilverlightCanvas2;
Canvas.SetLeft(objBlankSilverlightWindowControl2, (double)300);
Canvas.SetTop(objBlankSilverlightWindowControl2, (double)310);

// Add Canvases to a collection that will be checked as possible drop points
colPanels.Add(SilverlightObjects.LayoutRoot);
colPanels.Add(objSilverlightCanvas1.LayoutRoot);
colPanels.Add(objSilverlightCanvas2.LayoutRoot);

// Add Windows to the Page
this.LayoutRoot.Children.Add(objSilverlightWindowControl);
this.LayoutRoot.Children.Add(objBlankSilverlightWindowControl1);
this.LayoutRoot.Children.Add(objBlankSilverlightWindowControl2);
}

The SilverlightObjects.xaml control uses an instance of the parent control to wire-up the mouse events to detect when an element is being dragged.


public SilverlightObjects(Page objPage)
{
InitializeComponent();

// Add delegates to the parent to allow it to handle the drag and drop
FrameworkElement objFrameworkElement1 = (FrameworkElement)this.DragElement1;
objFrameworkElement1.MouseLeftButtonDown +=
new MouseButtonEventHandler(objPage.objFrameworkElement_MouseLeftButtonDown);
FrameworkElement objFrameworkElement2 = (FrameworkElement)this.DragElement2;
objFrameworkElement2.MouseLeftButtonDown +=
new MouseButtonEventHandler(objPage.objFrameworkElement_MouseLeftButtonDown);
FrameworkElement objFrameworkElement3 = (FrameworkElement)this.DragElement3;
objFrameworkElement3.MouseLeftButtonDown +=
new MouseButtonEventHandler(objPage.objFrameworkElement_MouseLeftButtonDown);
}

Note, the only way to get an instance of the parent control when a control has been dynamically added is to pass an instance of that parent to the control when the control is added. The mouse events must be attached to, and handled by, the parent not the child control for the communication between windows to work.

When the mouse starts to drag an element, the element is checked to see if it’s tag contains “[draggable]“. If it does, the element is removed from the Canvas it is on and placed on the main Canvas.


void objFrameworkElement_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//Start Drag
FrameworkElement objFrameworkElement = (FrameworkElement)sender;
objFrameworkElement.CaptureMouse();

// Set the starting point for the drag
StartingDragPoint = e.GetPosition(objFrameworkElement);

// Remove the element from it's control and move it to the parent
// if it's Tag contains the words [draggable]
if (objFrameworkElement.Tag.ToString().Contains("[draggable]"))
{
Panel objParent = objFrameworkElement.Parent as Panel;
objParent.Children.Remove(objFrameworkElement);

this.LayoutRoot.Children.Add(objFrameworkElement);
MoveToTop(objFrameworkElement);
UpdateElementPosition(objFrameworkElement, e.GetPosition(this.LayoutRoot));
}

objFrameworkElement.MouseMove += new MouseEventHandler(objFrameworkElement_MouseMove);
objFrameworkElement.MouseLeftButtonUp += new MouseButtonEventHandler(objFrameworkElement_MouseLeftButtonUp);
}

The code to move an element being dragged is the same whether or not the element has been moved to the main Canvas or not.


#region MouseMove
void objFrameworkElement_MouseMove(object sender, MouseEventArgs e)
{
FrameworkElement objFrameworkElement = (FrameworkElement)sender;
Canvas objCanvas = (Canvas)objFrameworkElement.Parent;
Point Point = e.GetPosition(objCanvas);

UpdateElementPosition(objFrameworkElement, Point);
}
#endregion

When an element is dropped, this code is used to determine if the element will simply be placed inside a control, or if the ImportContent method will be called:


#region MouseLeftButtonUp
void objFrameworkElement_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//Stop Drag
FrameworkElement objFrameworkElement = (FrameworkElement)sender;
objFrameworkElement.ReleaseMouseCapture();

objFrameworkElement.MouseMove -=
new MouseEventHandler(objFrameworkElement_MouseMove);
objFrameworkElement.MouseLeftButtonUp -=
new MouseButtonEventHandler(objFrameworkElement_MouseLeftButtonUp);

// If it is an element marked [draggable]
// try to drop it on a panel stored in the colPanels collection
if (objFrameworkElement.Tag.ToString().Contains("[draggable]"))
{
Point tmpPoint = e.GetPosition(null);
// Build a list of elements at the current mouse position
List<UIElement> hits = (List<UIElement>)this.HitTest(tmpPoint);
// Loop through all the Panels in the colPanels collection
foreach (Panel objPanel in colPanels)
{
if (hits.Contains(objPanel))
{
// Grab the position of the element being dragged in relation to it's                position on the
// main canvas and its position in relation to the panel it may be dropped on
Point mousePos1 = e.GetPosition(objPanel);
Point mousePos2 = e.GetPosition(objFrameworkElement);

// Remove the element from the main canvas
this.LayoutRoot.Children.Remove(objFrameworkElement);

// Import content
// Get a reference to the parent of the current panel
UserControl objUserControl = (UserControl)objPanel.Parent;
// See if that parent implements an interface called "ImportContent"
object objObject = objUserControl.GetType().GetInterface("ImportContent", true);

// If the object is not null then the parent object has a method             called "ImportContent"
if (!(objObject == null))
{
// Create a parmeters array
object[] parameters = new object[1];
// Add the elemnt that is being dragged to the array
parameters.SetValue(objFrameworkElement, 0);
// invoke the "ImportContent" on the parent object passing the parameters array that
// contains the element being dragged
bool boolImport = (bool)objUserControl.GetType().InvokeMember("ImportContent",
BindingFlags.InvokeMethod, null, objUserControl, parameters);

// If the import was not successful simply add the element to the panel
if (!boolImport)
{
// Add the element to the panel
objPanel.Children.Add(objFrameworkElement);
Canvas.SetLeft(objFrameworkElement, mousePos1.X - mousePos2.X);
Canvas.SetTop(objFrameworkElement, mousePos1.Y - mousePos2.Y);
}
}
else
{
// The parent object does not implement the "ImportContent" Interface
// Add the element to the panel
objPanel.Children.Add(objFrameworkElement);
Canvas.SetLeft(objFrameworkElement, mousePos1.X - mousePos2.X);
Canvas.SetTop(objFrameworkElement, mousePos1.Y - mousePos2.Y);
}
break;
}
}
}
}
#endregion

The ImportContent Method

Each control determines what content it will import. The control must implement an interface called ImportContent that accepts a FrameworkElement as a single parameter and returns a bool:


interface ImportContent
{
bool ImportContent(FrameworkElement objFrameworkElement);
}

In this example the SilverlightCanvas1.xaml control is coded to only import text from any TextBlocks.


#region ImportContent
public bool ImportContent(FrameworkElement objFrameworkElement)
{
// This import method will only import text content contained
// in TextBlocks that are placed on a Canvas

StringBuilder StringBuilder = new StringBuilder();
Canvas objCanvas = objFrameworkElement as Canvas;

// If the element being imported is not a canvas return false
if (objCanvas == null)
{
return false;
}

try
{
// Loop through all the UIElements in the Canvas
foreach (UIElement objUIElement in objCanvas.Children)
{
// Try to cast the UIElement as a TextBlock
TextBlock objTextBlock = objUIElement as TextBlock;
if (objTextBlock != null)
{
// Add the contents of the TextBlock to the output
StringBuilder.Append(String.Format(" {0}", objTextBlock.Text));
}
}
}
catch
{
return false;
}

// Was content in the output ?
if (StringBuilder.Length > 0)
{
// Add output to the Textbox display
this.txtContent.Text = StringBuilder.ToString();
return true;
}
else
{
return false;
}
}
#endregion

Summary

This example demonstrates a method for dealing with the “unknown”. With SilverlightDesktop, modules can be created by different developers that have no knowledge of each other, yet using a method such as this, content can be exported and imported between them.

Author: Michael Washington

Michael Washington is a website developer and an ASP.NET, C#, and Visual Basic programmer. He is has been named Microsoft MVP in ASP.NET for two straight years. He is a DotNetNuke Core member and has served for over three years. He is the author of the module development chapter in Building Websites with VB.NET and DotNetNuke 4 (Packt Publishing).

He has a son, Zachary and resides in Los Angeles with his wife Valerie.

10 Silverlight 2 gotchas resolved: By Antoni Dol

Note: This article is submitted by Antoni for Silverlight 2 Beta 2 - Articles Competition.Thanks a lot, Antoni! Hello All, Anton is a designer, so this article is biased towards designers. Please drop a comment if you like it.

Contents

  • Canvas rules
  • One way to make Color resources
  • Limited Fonts
  • No BitmapEffects
  • No Paging facility
  • Limited Resource facilities
  • Significant Transparency
  • StaticResources only
  • XML Data Binding in code only
  • Lack of important controls: DropdownList and PasswordBox
  • Links
  • Author Bio

This Silverlight 2 development kick start helps you get over initial hurdles and clears the path for faster results.

Coming from projects in which WPF design experience was established, the step to developing in Silverlight 2 was not an easy one. Even though I anticipated getting disappointed and even annoyed by times, there were several gotchas that baffled me. Some of those can still be found in the current Beta 2 release, but others are resolved to a degree that makes for a workable Silverlight 2 environment. These include Canvas rules, Color resources, limited fonts, no BitmapEffects, no paging facility, limited resource facilities, significant transparency, StaticResources only, XML Databinding, and the lack of some important controls. I’ll let you in on this treasure trove and tell you all about these 10 Silverlight 2 gothas resolved.

1. Canvas rules

As a designer it is fairly easy to get XAML. You export it from Illustrator using a special plug-in or you copy and paste it from Expression Design. You can export it from Expression Design too, with more elaborate options for WPF and Silverlight. Still, the Canvas layout panel rules in all these exports. The Canvas places elements on absolute positions using Canvas.Left and Canvas.Top attached properties. Any Canvas can be placed on any other Canvas. The export from an entire Illustration will likely be Canvas galore. You’ll lose control, get fed up with canvasses, but can’t get rid of them because every layout position of every element depends on one or more canvasses, anchored somewhere in the bulk of XAML markup. Endless strings of Path streamgeometry data make finding a specific Canvas sheer hell. To cut to the chase: don’t let your layout get out of control.

First, export only small and modular elements from Illustrator or Expression Design illustrations. Stay on top of it by confining certain elements to a Canvas and placing this in a layout that actually makes use of the extended layout features of Silverlight. Secondly, before exporting that element, copy it to a new page and place it on the exact 0,0 coordinates. Finally, remove any canvasses from an export before committing it to you layout. You’ll have to rearrange the elements using Grid and StackPanel panels. What you will gain is the ability to create and control more flexible layouts.

2. One way to make Color resources

This is the only way to create a Color Resource in Silverlight:


<Color x:Key="clrAccent">#FF800000</Color>

Other ways to formulate the color code, which may be valid in WPF, don’t work in Silverlight. Don’t forget that many Backgrounds and Fills use Brushes, so create a Brush Resource for every Color Resource too:


<SolidColorBrush x:Key="brsAccent" Color="{StaticResource clrAccent}" />

Why would you want to do this? You can create color palettes and swap all colors in your application on the fly. Your clients will love it, you will gain time. Also, creating a color palette will keep the amount of colors used in your application to an acceptable level, making a harmonious design possible.

Another option is to use predefined colors using the White, Red, Black and some 200 other keywords that are automagically converted to valid color values by the platform. Your choice is limited and not every color that you might need is available as predefined color. Nobody stops you when you just use hex color codes right into the XAML. You will have entered an environment where changing the color of elements in one sweep is virtually impossible. Then again, not every client want a complete overhaul of the colors in your application now, do they?

3. Limited Fonts

This one caught me by surprise. I was used to Segoe UI in my interfaces, not only because it is the font recommended by the User Experience Guidelines, but just because it is a beautiful and open typeface, obviously especially designed for use in UIs. In WPF it was easy to set a font for an entire application using a Typed Style on the Control control. That ensured that all controls that inherit from Control use the same FontFamily and base FontSize. No go in Silverlight 2. Apart from it being impossible to set a Style to a Type (you have to use a Key for a Style and you have to use this key to implement the Style) you have access to only nine fonts that are normally available on computers these days. These are about the same that Web developers traditionally adhere to, because they have little to no control over installed fonts on a client PC.

To use a different FontFamily, you’ll have to add the font files to your Silverlight project as a Resource –which will increase the download. Note that you also have to add Bold and Italic versions of the font to your project if you want to use those. Refer to it using this XAML:


<TextBlock FontFamily=”segoeui.ttf#Segoe UI” FontSize=”12” />

Better even is to create a series of Styles for all your text controls and try to cover all your bases. You’ll also have to accommodate for several other controls (like Buttons and TabItems), because you can set the FontFamily on those as well.


<Style x:Key=”TextBlockFont” TargetType=”TextBlock”>
<Setter Property=”FontFamily” Value=”segoeui.ttf#Segoe UI” />
<Setter Property=”FontSize” Value=”12” />
</Style>

To finish this, set the Style on all TextBoxes:


<TextBlock Style=”{StaticResource TextBlockFont}” />

4. No BitmapEffects

The advantage of having no DropShadow, OuterGlow, Bevel and Blur effects available in Silverlight is that you cannot overdo     using them. The danger of these effects is to use them when it is unnecessary. When you want to make a real subtle shade behind a container you can’t do it. Not easily anyway. I have two solutions that you might use: RadialGradients and Blends. The first is a simple radial gradient that allows you to make a shadow or a glow behind your drawing. The drawback is that is has to be an ellipse. Actually, when I think about it, you could clip this ellipse using a clipping path on the filled object.

The other solution is to use blends (notice the lower case b). Expression Design actually supports blends with a little dialog. This allows you to take two complex Paths and morph the first in the second. Create a copy and a larger copy of your Path and center the two and give them a 95% transparent Black Background. Blend in 10 steps from the first copy to the second. For a rectangular container, you can also use a Border with a 1 pixel Margin and a 95% transparent Black Background:


<Border CornerRadius="25" Margin="1" Background="#0C000000">
<!-- 9 more borders like this -->
</Border>

The almost transparent background will add up to a nice shade of gray, working with any color behind it. You’ll have to decrease any CornerRadius you use by 1 pixel, to make the effect work correct. Likely, a Grid layout panel inside and outside the collection of Borders will make your live easier. This way you can create a shadow, a glow and even a bevel if you choose your colors wisely.

5. No Paging facility

You can link to any other HTML page using HyperlinkButtons in Silverlight. That page can contain a plug-in with a different screen or set of screens in your application. You can also hide and show overlapping panels using code animations (be sure to read gotcha 7 about significant transparency when you use this method). When you want to swap XAML files within you current application it is a different story. There is no paging functionality in Silverlight.

The concept of Page in earlier Silverlight versions is replaced by UserControl as your RootElement. The answer is to replace the RootVisual in your app.xaml code behind file to load this new XAML file:


startupUI = new Silverlight.Welcome();
Grid root = new Grid();
root.Children.Add(startupUI);
this.RootVisual = root;

You can find enough examples online on variations on how to do this. One will fit your case.

6. Limited Resource facilities

Unlike in WPF using Resources in Silverlight is limited. Without the MergedDictionaries making external Resource Dictionaries a no brainer in WPF, Silverlight lacks flexibility in using Resources. MergedDictionaries would have made it possible to have a RD per Control or have an application wide Stylesheet using XAML. As a result the only possible application wide Resource Dictionary app.xaml should now be swamped with Styles addressing various parts of the UI, be it Colors, Brushes, Styles or ControlTemplates. You can override these Application Resources with Local Resources by using the <UserControl.Resources /> collection and using the exact same Keys. You could even go further and use the Resource collection of layout panels to overrule the Local Resources. <Grid.Resources /> will do just that. Apart from that Silverlight supports Static Resources and doesn’t allow for implicit Stylings with the use of a TargetType only. BasedOn Styles are also a no go.

Another story is placing Animations in app.xaml. I like to have my animations apart from the rest of the XAML, because they can become very lengthy and are not really relevant to the functionality of the UI. The animations have to be started using Event Handlers in a Code Behind file in Silverlight instead of the Triggers used in WPF. The Triggers were able to connect to the target object for an animation. The Event Handlers won’t do that for you. You’ll have to find the Animation Resource using App.Current.Resources.Contains(name), assign it to a Storyboard object in the Code Behind file of your page and set the Target element for that Storyboard before starting the animation: Storyboard.SetTarget(Storyboard1Resource, Rectangle1);

7. Significant Transparency

I have been taunted by this one for a long time. It has two sides to it. The first is that transparent elements overlapping parts of your UI (like a Glow from White to Transparent) block all interactivity with the elements under it; the other is that invisible elements may still receive click events and result in actions that you cannot trace to the visible UI.

Both sides have very easy solutions. To stop overlapping semi-transparent elements preventing any interactivity, set its IsHitTestVisible property to false. The catch is that in the Expression Blend Interface this is not picked up. In Blend, you still won’t be able to touch the overlapped elements. My choice is to poke the eye next to the Elements’ name in the Objects and Timeline palette and thus Hide it in Blend.
To keep invisible objects from being clickable, you’ll have to collapse them. Set Visibility=”Collapsed” in XAML or this.Visibility=Visibility.Collapsed in code to accomplish this. You may have to create some code to make parts of you UI visible before allowing your users to work with them, while collapsing all other parts of the UI.

8. StaticResources only

The use of StaticResources only has two consequences. The Resource has to be loaded before it is used. The Resource cannot be changed afterwards (hence Static). For you this means placing all Resources in code before an attempt to use it. For example Background=”{StaticResource brsAccent}” will pop up an error when the Brush Resource  brsAccent is not in de Application Resources or the Local Resources. What you lose is the ability to update Resources real time, like in swapping Skins. You’ll have to find other tricks do achieve that.

9. XML Data Binding in code only

One of the powers of the Expression Blend UI is the ability to create a data binding to a XML data structure using nothing but mouse clicks. This is not working for Silverlight 2 Beta 2. As you can see the +XML tab in the Data panel is disabled. This should be resolved by the Blend Team in the coming months, but it doesn’t mean that you cannot use XML Data Sources to bind to. You can actually use LINQ to find the element to bind to. You’ll have to do that in code for now. Check the Silverlight SDK for the correct procedures.

10. Lack of important controls: DropdownList and PasswordBox

Last, but not least, important controls are still missing from the Beta 2 plug-in. Of course we cannot have the entire WPF Framework to our disposal, but some controls we cannot do without. Fortunately there’s a workaround for some of these, which may be reason to leave them out in the first place. You can create a DropdownList using a Togglebutton and a ListBox. The ToggleButton governs the ListBox visibility. The ListBox itself shows a collection of ListBoxItems and has a scrollbar when necessary. You should update the ToggleButton Content with the value of the selected ListBoxItem, so it reflects the users’ choice. You can style both controls as you like to create a coherent DropdownList control.

The code to create a PasswordBox control from a TextBox contains a lot of string handling, but it works. I’ve used the solution from Chris Pietschmann with success in my last project.

So, having removed the primary obstacles to Silverlight 2 Development, consider yourself warned and ready to create stunning applications in Silverlight 2. Expect more improvements of the plug-in before it is final. Not every snag may be gone, but your developer life will get better. Using these solutions to 10 Silverlight 2 gothas you should be able to get on your way right now.

Links:

Author Bio:

Antoni Dol is Senior Designer at the Dutch Internet service bureau Macaw. He graduated as illustrator at the Gerrit Rietveld Academy in Amsterdam, studied Advertising at the Academy of Art in Rotterdam and was a freelance illustrator for three years. Growing with the internet he started as a web designer in 1995 and from 1996 he is designer at the internet service bureau Macaw. He has worked for companies like KPMG, NedTrain, Wolters Kluwer, Univé Insurances, Bijenkorf e-commerce, city of The Hague, Rabobank en Microsoft in the Netherlands. He received a Creative Excellence Award at the Web Page Awards in 2001 en the NedTrain intranet was one of the 10 best of 2005 according to Usability expert Jakob Nielsen. Antoni has experience in Windows Presentation Foundation from October 2006 onwards and worked on applications in WPF, such as a large system for welfare administration and a simulation game. Antoni writes articles for internal and external Macaw publications and for the Dutch Software Development Network. He was the runner up in the Microsoft Expression Designers Contest in the Netherlands with a Silverlight website created in Expression Design en Expression Blend. He wrote the “XAML Handbook” in Dutch and has a blog called “Addendum” with additions to the book at http://antonidol.com. Antoni works with XAML in WPF en Silverlight projects on a daily basis.

Creating a Silverlight game: By Boyan Mihailov

Note: This article is submitted by Boyan for Silverlight 2 Beta 2 - Articles Competition.Thanks a lot, Boyan! Hello All, Please drop a comment if you like it.

Contents

  • Introduction
  • Home Page
  • Game Page
  • Congratulations Page
  • Statistics Page
  • Conclusion

Sourcecode : CowsAndBulls.zip (86.2 KB)
Online Demo : Cows & Bulls Game

Introduction

I am a great fan of Silverlight. I have never liked 1.0, but when version 2.0 was released I was very amazed. I created a few solitaire games. Now I decided to create a new game and to describe the problems I have encountered to you. First I decided to write an article about creating a Silverlight application for Facebook. But subsequently I decided to divide the article in two parts – creating a Silverlight application, which is a game in this occasion, and integrating it in Facebook.

I am going to create a game, called Cows & Bulls. You play that game for time. It supports a list of all players and their time.

Beginning

I will use a strong pattern in my application, so I need to put the common styles in the application resources. Now I can access them from everywhere in my application.


<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="CowsAndBulls.App">
<Application.Resources>

</Application.Resources>
</Application>

Game Structure

The structure of my game looks like this (the arrows represent the possible transitions between the pages). I am going to describe you the most interesting parts of each page; what kind of problems I have encountered and how I have solved them.

Home Page

It contains nothing more than a list of links to other pages. In this application I have changed the default style of the ListBox control in order to adapt it for my need. How is this achieved? You have to change the Template of the control. You can read my article for more information.


<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Grid>
<ItemsPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

As ListBox is an item control it needs ItemsPresenter to represent its items. When you have predefined the default style of the ListBox, you need to predefine the default style of the ListBoxItem, too.

Game Page

The game page contains three major controls:

  • Game Grid
  • Timer
  • Animated Assistant

I needed something like a ListBox, but I wanted one ListBoxItem to contain three subitems. DataGrid is very good for this purpose, because it supports columns. But it would make my application bigger and slower, because it has many other properties, which I do not need in this case. That’s why I decided to create my own control. It is nothing more than a predefined ListBox, of course. Here is the ControlTemplate for the ListBoxItem.


<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<TextBlock Grid.Column="0" Text="{Binding Path=Number}" TextAlignment="Center" />
<TextBlock Grid.Column="1" Text="{Binding Path=Cows}" TextAlignment="Center" />
<TextBlock Grid.Column="2" Text="{Binding Path=Bulls}" TextAlignment="Center" />
</Grid>
</ControlTemplate>

Data binding is one of the most fundamental techniques in WPF and Silverlight as well. I have a class, called Player, which represents the player’s details (you can see its diagram). When I change the DataContext of my custom control, each TextBlock immediately “gets” the value of the property it is bound to.

To compare the players, I need to know the exact time, each has completed the game. That’s why I have created a simple timer. It uses a DispatcherTimer - a timer that is integrated into the Dispatcher queue which is processed at a specified interval of time and at a specified priority. Timers are not guaranteed to execute exactly when the time interval occurs, but are guaranteed not to execute before the time interval occurs. This is because DispatcherTimer operations are placed on the Dispatcher queue like other operations. When the DispatcherTimer operation executes, it is dependent of the other jobs in the queue and their priorities.

If a Timer is used in a WPF application, it is worth noting that the Timer runs on a different thread then the user interface (UI) thread. In order to access objects on the user interface (UI) thread, it is necessary to post the operation onto the Dispatcher of the user interface (UI) thread using Invoke or BeginInvoke. Reasons for using a DispatcherTimer opposed to a Timer are that the DispatcherTimer runs on the same thread as the Dispatcher and a DispatcherPriority can be set.


DispatcherTimer timer;
long seconds;

public Clock()
{
this.timer = new DispatcherTimer();
this.timer.Interval = TimeSpan.FromSeconds(0.999);
this.timer.Tick += new EventHandler(timer_Tick);
}
private void timer_Tick(object sender, EventArgs e)
{
TimeSpan diff = TimeSpan.FromSeconds(++this.seconds);
}

As you can see, I have set the interval of the timer to 0.999, instead of setting it to 1. This is because the timer needs a little time to execute the code in timer_Tick method. Well, the timer is not the perfect one, but it simulates a real chronometer.

I have added a simple animated assistant, which “tells” the player some things. It moves his eyes up and down. It uses two DoubleAnimations to achieve this. Pay attention that when you want to change an attached property, you have to surround it with rounded brackets.


<Storyboard x:Name="EyeAnimation">
<DoubleAnimation Storyboard.TargetName="LeftEye" Storyboard.TargetProperty="(Canvas.Top)" RepeatBehavior="Forever" From="30" To="40" Duration="0:0:4" AutoReverse="True" />
<DoubleAnimation Storyboard.TargetName="RightEye" Storyboard.TargetProperty="(Canvas.Top)" RepeatBehavior="Forever" From="30" To="20" Duration="0:0:4" AutoReverse="True" />
</Storyboard>

DoubleAnimation is very powerful when you want to change the value of property of an object bit by bit. Setting AutoReverse to true reverses the animation and you see an endless (when you set RepeatBehavior to forever) fluent animation.

Congratulations Page

It is shown when a player completes the game. Here it writes his name. His details are then send to the Statistics Page, where they are send to the server.

Statistics Page

This page show the top players, which have the best time in completing the game. In this page we made a web request to send player’s details and get the top players. Update method, shwon above on the Player class diagram processes a web reuqest through a WebClient. This class provides common methods for sending data to and receiving data from a resource identified by a URI. Furthermore it processes all request in another thread. When you make calls to web service or other time-taking resources, it is very essential to put the code in another thread. However, if you need more specific options when communicating with a web server, you have to use HttpWebRequest. It provides support for additional properties and methods that enable the user to interact directly with servers using HTTP.

The following code posts player’s details to the web server. In this case I have created a simple PHP file and put it on my own server. The web client does request to this file, which manipulates the data.


WebClient client = new WebClient();
string postData = "Name=PlayersName&Time=00:02:43";

client.Encoding = System.Text.Encoding.UTF8;
client.Headers["Content-type"] = "application/x-www-form-urlencoded";
client.UploadStringCompleted += new UploadStringCompletedEventHandler(client_UploadStringCompleted);
client.UploadStringAsync(new Uri("http://somewebsite.com/somefile.php"), "POST", postData);

The default encoding for all forms is application/x-www-form-urlencoded. A form data set is represented as follows:

  1. The form field names and values are escaped: space characters are replaced by ‘+’, and then reserved characters are escaped
  2. The fields are listed in the order they appear in the document with the name separated from the value by ‘=’ and the pairs separated from each other by ‘&’

You can read more about managing form data in the W3 website.

When you make request to a web server you may encounter a cross-domain policy problem. You can read more about this in Karen’s blog. In Silverlight, we send cookies & authentication with each cross domain request. Because of this, web service authors need to be careful to separate their 3rd party accessible APIs from their main site. You need to configure a file, called clientaccesspolicy.xml, in order to set the permissions for calls from Silverlight applications. It looks like this:


<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="Content-Type">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>

When player’s details are successfully saved, we have to get the top players list.


webClient.Encoding = System.Text.Encoding.UTF8;
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri("http://somewebsite.com/somefile.php"));

DownloadStringCompletedEventArgs contains a property, called Result. It returns the result from the server as a string. My PHP file returns the result in XML format. Now I can use LINQ to XML to obtain the players’ details. LINQ to XML is very powerful technique and it’s so great that Silverlight 2 supports it. You need to add a reference to System.Xml.Linq in your project in order to use it. And here it is:


XDocument doc = XDocument.Parse(e.Result);

var players = from player in doc.Descendants("Player")
select new Player
{
Number = int.Parse(player.Attribute("No").Value),
Name = player.Element("Name").Value,
Time = player.Element("Time").Value
};

Then I just set the ItemsSource of my ListBox control to players and they show up.

Conclusion

Creating games with Silverlight is so easy and pleasant. I have uploaded this game on my web site, so you can try to beat it. You can view its source and post comments on it. Have fun!

References