Wednesday, March 26, 2008

Using and embedding fonts in Silverlight 2

There are multiple options to embed your fonts in Silverlight 2:

1. Using font as "Content"

First, embed the font as "Content" (see Properties, Build action). With this option, you can use the following method to set the font:

codesnippet1

The "problem" with this can be that the fontfile is embedded in the .XAP file. Therefore is available to anyone who wants to use the fontfile:

screenshot1

 

2. Using font as "Embedded Resource"

The advantage of using this method is that the fontfile is compiled with the DLL. So this makes it hard (maybe even impossible?) to retrieve the fontfile.
If it is still possible (maybe with a decompiler), at least it makes it less easy to get it.

When you want to use this method, first set the Build action to "Embedded Resource".

Next, use the following code to display the correct font (click to view larger size image):
 codesnippet2

 

3. Using font as a downloadable object

This has no real advantages to the above mentioned methods. Maybe if you use a font across multiple sites or something...

First, copy the font file to the ClientBin folder and use a WebClient to download the font:

codesnippet3

When the async request is completed, set the font:

codesnippet4 

That's it for now!

 

Download the source here

Sunday, March 23, 2008

Unpacking ZIP files in Silverlight 2

One of the nice features in Silverlight 1.1 alpha was, in my opinion, the use of zipfiles and being able to use files from a zipped file by using the Downloader object.

In Silverlight 2 the Dowloader is replaced with the WebClient. Which is not a bad thing, but it seems to be missing the ability to use zipfiles. Or I've missed it somehow...

Anyway, I stil wanted the thumbnails on my site to be downloaded using a ZIP file simply because it makes it smaller and easier to handle.

In the past I've been using ICSharpZipLib so I figured I'd give that a try.
After adding ICSharpZipLib project to my Silverlight project I had to change a few things, mostly changing ArrayLists to generic Lists and a few minor other thing. My SharpZipLib project is available for download (bottom of this article) but be sure to test it thoroughly, I've only used a small part of the library.

How does it work

It was quite easy to implement this:

ICSharpZipLib contains a ZipInputStream which converts an existing Stream to a ZipInputStream.

The e.Result property (Stream) of the OpenReadCompletedEventArgs can be used in the constructor of the ZipInputStream class.

After creating the ZipInputStream, a call of the GetNextEntry method will return a ZipEntry (zippedFile). So we need to create a loop to get through all of the files in the ZipInputStream:

codesnippet1

codesnippet2

In between these 2 snippets is the code for handling the files.
A MemoryStream is created for reading the buffer of the outputStream of the zippedFile.

Handling the MemoryStream for each filetype

The extension of the file in the zip is used by the switch to determine which method is called for handling the MemoryStream:

codesnippet3

Inside these functions the stream is used as a parameter for a SetSource of a BitmapImage in case of an image filetype:

codesnippet4

or as a parameter for a StreamReader in case of a text file:
codesnippet5

or as the stream parameter for the SetSource of a MediaElement:

codesnippet6 

The last one, however, crashes IE. Not sure why this happens. When debugging it seems to work fine, but it crashes when playing with a System.CrossAppDomainMarshaledException (crossdomain error) even when using a clientaccesspolicy.xml or a crossdomain.xml.

 

Click here to download SharpZibLib for Silverlight

Click here to download the entire solution

Thursday, March 6, 2008

First Silverlight 2 impressions

After the first few days I wanted to share some of my first Silverlight 2 experiences.

Nice controls!

To be honest, I was very impressed with the set of controls that are supplied. They look great and in the demo app I've downloaded they seem to work well too.

On the downside, after the first day I've had a few dissapointments as well:

No inheritance in UserControls

According to someone on the Silverlight.net forum, it's a "limitation", but I think it's a bug:

It it not possible to use inheritance in a UserControl even if the Base class inherits the UserControl class. When building you get the error:
"Partial declarations of 'CLASSNAME' must not specify different base classes" in the file CLASSNAME.g.cs (g = generated).

When you open the .g.cs file and remove the base class from it, the project compiles fine and also seems to work fine. Looks like a bug in the implementation of Silverlight in Visual Studio.

**************************** UPDATE ****************************
I've posted my problem on the SL.net forum (like some more people) and got some nice responses. Some even seem to work almost right :):

Check out this forum thread: http://silverlight.net/forums/p/10970/34988.aspx

So it is possible but has some peculiarities. For instance, when opening a file in Blend it gives an error. When you have no need for that, it's no problem, but I would like my designers to still have the ability to change things in the design after I used inheritance on the control.
Not quite sure what to think of this...

 

XAP project shortcoming?

This could be my lack of experience in SL2, but again, it's my first impression. If I find a way this does work, I'll post it as well :)

When having multiple Silverlight pages (or applications as they are called now) in a single Silverlight Project it seems impossible to load any other than the default Page.xaml:

- When using the "html" <object> method: it expects a parameter with a xap file, xaml files are not allowed.
- asp:Silverlight control also needs a xap file. asp:xaml doesn't work.

I also posted this at the silverlight.net forum so if I get any solution I'll let you know.

**************************** UPDATE ****************************
There is an option by setting an initParam with the name of the startup control you want to use. I'm not sure if I like this option, but it's a workaround.

WebClient instead of Downloader, improvement?

Okay, probably a better control I assume. Hmmm, dunno about that after implementing it. For a simple thing as loading an image from a zip file (thanks Marnix)....

Old school (1.1 alpha) code:

codesnippet1

New school (2 beta) code:

codesnippet2

Seems like more lines of code. Doesn't necessarily mean that it's a worse solution than the SL1.1 one, but it definitely makes it easier to make an error.

I think that they (MS), maybe in a later version, want to support bitmap effects like Flash does (blurring, etc). Maybe that's the reason they chose for the addition of a bitmap object.
Time will tell.

Uri inconsistency

As Imran Shaik posted on his blog, Silverlight 2 beta 1 is inconsistent when it comes to relative Uri.
The relative path should be the path from the root of the website, as it is in SL1.0 and as it was in SL1.1.

In SL2 beta 1, the path in design is relative to the root of the site, but when running the app, it is relative to the location of the XAP file. So when downloading "thumbnails.zip" using the WebClient it looks for thumbnails.zip in the ClientBin folder instead of in the root of your website.

Setting the WebClient.BaseAddress to the root of the site doesn't seem to work either.

That's what I've encountered up until now. So far, I'm not very positive about this release. I was much happier with SL1.1 alpha, but it's only the first few days.

I'll keep you informed....

Monday, March 3, 2008

Getting Live Messenger Status and display it in Silverlight 2.0 alpha

In expectation of Silverlight 2.0 I decided to do some experimenting with some of the Live API's.

I build a small app which shows my Live Messenger status. And can also show other peoples status if they gave permission.

For now, all you see is a big Messenger icon I created in XAML. I'm not a designer, but you can imagine it's possible to create some nice visuals and animations instead of just displaying a still, like I did.

 

How does it work?

The API Microsoft supplies for this is a JSON API. So the examples they supply are in javascript so I had to find a way to get the data that is returned from the API in javascript into my Silverlight control.

 

Getting acces to Silverlight functions from Javascript

- Make your class Scriptable so that it's possible for Javascript to access methods and properties in your class.

- Also make the properties and/or methods you want to use from JS Scriptable.

It should look something like this:

codesnippet2

codesnippet1

Next, we need to create the call to the API from Javascript.

 

Calling the API

This can also be reviewed at the Microsoft site (http://msdn2.microsoft.com/en-us/library/bb936688.aspx).

The API can be called using an URL of this format:
http://messenger.services.live.com/users/[ID]/[resource]/[?queryparameters]

To call this API, you can use a javascript "include" in a webpage. By using a callback function you can read out the information returned by the API.

The script Microsoft provides looks like this:

codesnippet3

(be carefull, I added a return in the url otherwise it would be too long to fit on the screen)

Now, I wanted to set the id dynamically, so I added a literal to the page in which the script tag is generated from serverside code.
Place this Literal (or script) directly above the body closing tag.

The server side code I use to fill the Literal looks like this:
codesnippet6

Handle the callback

Next is the javascript with the functions to handle the callback and to set the properties in the silverlight object:

codesnippet4

This goes in a separate javascript file I called "MessengerAPI.js" and should be referenced in the head of the html.

 

Calling the API after Silverlight object is loaded

After first running into some problems with calling the setStatus method, it turned out to be a timing problem. setStatus cannot be called before the Silverlight control is completely loaded.

So the trick is to create a onloaded eventhandler in the createSilverlight function and set the variable "control" in the handler so you're 100% sure the control is loaded, like this:

codesnippet5

Finishing up

To be able to see the status of other people, Microsoft requires you to:

1. Have a privacy statement on your site, which they can refer to

2. Have a return URL where Microsoft can redirect to when the user has logged in and confirmed that your website can have access to their status information.

permission_live

Conformation on Live site

Next, I created a separate aspx page as a landingpage for catching the visitor who clickec "I accept" (ReturnUrl.aspx). In this page you can do lots of stuff, set cookies or save userdata in db (change your privacy statement accordingly).
At this time I just do a redirect to the default.aspx with the ID as a querystring parameter.

This brings us back to where we started.

screenshot

 

Click here to view a demo

Click here to download the source for this project

Saturday, March 1, 2008

Spinawards Showcase website in showcase on Silverlight.NET

The site my colleagues (http://www.amercom.nl) and I created as a showcase for the Spinawards entries has been placed on the Silverlight.NET site, in the showcase section!

http://silverlight.net/showcase/