Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Silverlight 2.0: Creating a basic animation through code

In my previous Silverlight post, I mentioned Silverlight 2.0 API now allows creating animations through code. While this wasn't possible with Silverlight 1.1 Alpha [you would have to create of piece of Xaml, declaring a storyboard with all animations markup, then load it into a Storyboard object by using XamlReader.Load() method], Silverlight 2.0 now makes it pretty easy.

The following animation code will create very basic fade out effect for given element, animating the Opacity property from 1 to 0 in one second:

private DoubleAnimation CreateFadeOutAnimation(string elementName)
{
    DoubleAnimation animation = new DoubleAnimation();
    Storyboard.SetTargetName(animation, elementName);
    Storyboard.SetTargetProperty(animation, "Opacity");
    animation.To = 0;
    animation.Duration = new Duration(TimeSpan.FromSeconds(1));
    return animation;
}
To start this animation, you'll have to add it to a new storyboard first:
Storyboard sb = new Storyboard();
sb.Children.Add(CreateFadeOutAnimation("myElement"));
sb.Duration = new Duration(TimeSpan.FromSeconds(1));
sb.Completed += new EventHandler(sb_Completed);
LayoutRoot.Resources.Add(sb);
sb.Begin();

The "myElement" above is the name of an visual element with this name, which has to exist in the context of the storyboard for it see it. Storyboard is added to the LayoutRoot's resources [LayoutRoot is the name of a default root Grid in Silverlight]. Instead of passing just a name of an element, you could as well pass in the actual element you're animating.

Note the Completed event hookup up there. This is because we want to stop and remove the animation from the resources when animation is done to clean things up a bit. Here's the handler:

void sb_Completed(object sender, EventArgs e)
{
Storyboard sb = (Storyboard)sender; sb.Stop(); this.Resources.Remove(sb); }

That's it. Of course you can add as many animations to the storyboard as you want - animating different elements at the same time, adding different animations, etc... In further posts we might add some more complexity to this basic sample.

Installing Expression Blend 2.5 March 2008 Preview

If you're considering installing Expression Blend 2.5 March 2008 Preview over Expression Blend 2 December Preview, make sure you uninstall the December Preview first, and then continue with March Preview installation. When doing vice versa, you'll lose some of the "Open in Expression Blend" shortcuts [allowing you to open solutions from Windows Explorer, or open (Silverlight) Pages from Visual Studio 2008].

Open from Explorer
Open from Visual Studio 2008

However, all is not lost if those shortcuts are gone after uninstalling December Preview. Simply repair the March Preview installation and you're back and ready to blend your solutions again.

Repair

First couple of days with Silverlight 2.0 Beta 1

Here's some notes on my first experience with Silverlight 2.0 Beta 1:

Installation

Runtime - quick, smooth. Like it's supposed to be.

Tools for Visual Studio 2008 - if running Alpha version of the tools, you'll have to uninstall it first. During the install, the VS2008 DVD might be required. For more info on this and a way around it, see this BradlyB's blog post.

Controls

Yeah! Loving it. Hey, there's a cool DataGrid control, and a DatePicker. Given that WPF still hasn't got those (out of the box), which technology would you rather pick for your next cool (demo) app? Silverlight or WPF?

If you've just begun learning these new technologies, I'd for sure recommend Silverlight - you're forced to work with a smaller programming model (a subset of that of WPF), and you're inevitably going to pick up some WCF in the process, if your application involves any kind of (disconnected) data.

Animations

With Silverlight's programming model moving closer to what we currently have in WPF, creating animations in Silverlight now feels much more comfortable. No need for creating animations by loading declaration code from Xaml any more; animations and storyboards can now easily be done from code; I'll post some sample code in next posts.

Connectivity

Lots of options here... WCF, HTTP based, JSON, RSS, Atom, ... There's, however, still a few limitations, some of them being: BasicHttpBinding-only for WCF (or no WS-* protocols for Web Services), some types (like XmlElement or XmlNode) can't be used in data contracts.

But... cross-domain service calls are now possible! The dreaded "cross domain call exception" is gone. Well, not entirely true, but if you play nice and/or have control over the service's web site, it's likely you won't bump into that wall again. For all other cases, using server-side proxies still seems like a possible way out.

Also worth noticing is that the managed Downloader class has been removed in favor of the WebClient class, which should offer the same functionality. Similarly, BrowserHttpWebrequest class was replaced with HttpWebRequest class.

Calling services is now asynchronous!

Other

Of course, there's a lot more... Some of the changes will be covered in my next posts on Silverlight 2.0 B1.

Mix'n'stuff

As expected, a lot of stuff was shown and discussed on the MIX08 keynote today:

  • eight - Internet Explorer 8 Beta 1 (download): better standards compliance, backward compatible mode, faster faster JavaScript implementation, embedded debugging tools, "activities" and "webslices" (custom extensions, deliverable simply by hacking up a couple of rows of XML),. ...
  • Silverlight 2.0 Beta 1 (download): it's here! With only 4.3MB in size, it delivers highly anticipated UI controls, along with a new testing framework, including tests for all Silverlight controls. Supports isolated storage for offline caching. Plus, Silverlight 2.0 now ships with a non-commercial Go-Live license and will also run on Nokia [Symbian] phones. Finally, if you've done any work with Silverlight 1.1, you're in for a serious code rewriting, as there's a lot of breaking changes in the code base. [That's, however, a good thing, because these changes bring Silverlight's programming model much closer to the the one in WPF]
  • Expression Blend 2.5 March 2008 Preview (download): Silverlight 2.0 Support
  • Silverlight Tools Beta 1 for Visual Studio 2008 (download): Add-on to Visual Studio for Silverlight 2.0 Beta 1 development. Better designer experience, although far from being nice as in Expression Blend.
  • Sea Dragon in action - Deep Zoom: take a look: Hard Rock Memorabilia [a bit quirky at the moment, I'm afraid] Want to make your own Deep Zoom creation? Download Deep Zoom Composer preview. And you can start with this User Guide.
  • The future of WPF: new controls, performance improvements, etc...

Watch the MIX08 keynote recording here.

[Update: here's a great preview of Silverlight 2.0 Beta 1 controls in action by Kathy Kam. Note that these controls are available in source code w/ full unit tests]

How well do you know your Culture?

When doing code reviews, I often stumble upon a piece of code with some culture-specific information hard-coded in it. One example of this being month names:

string[] months =
   
{
        "January",
       
"February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
       
"October",
        "November",
        "December"
   
};

This is all fine if your application is intended for English spoken users and all that, but hey - why try and duplicate something, what's already been done for you? CultureInfo class has all the information you need:

string[] months = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames;

And if you need the name of the months in some other supported language, all you have to do is ask [this one's for Slovenia):

string[] months = CultureInfo.GetCultureInfo("sl-SI").DateTimeFormat.MonthNames;

Then again, if all you need is month names in shortened form, the class can also help:

string[] months = CultureInfo.CurrentCulture.DateTimeFormat.AbbreviatedMonthNames;

If you're after just one specific month name, it will bi provided for you [the following line will get you February - obviously]:

string month = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(2);

And so on... The same pattern applies for day names, etc. If there is anything specific that you would want to know about a certain culture, CultureInfo class will give you all the information you need. Given these possibilities, one can even create a custom culture using the CultureAndRegionInfoBuilder class. There's quite a few examples of where this would come in useful.

One thing to note though: The MonthNames properties described above will return you the string array of 13 items; although majority of cultures have 12 months in a year, a few apparently have 13, so be aware of that when using these properties. If month names list is intended for a data source that can be bound to, you may want to return the actual number of months. The following method will return the actual number of months in a given year:

int mothCount = CultureInfo.CurrentCulture.DateTimeFormat.Calendar.GetMonthsInYear(DateTime.Today.Year);

The other way would be just skipping the empty months. There are again, several ways to do this - today, the weapon of choice is fashionable - Linq [or rather - its extensions], although it's most likely not the fastest way of doing it:

string[] cultureMonths = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames;
string[] months = cultureMonths.TakeWhile<string>(month => month.Length > 0).ToArray<string>();

The TakeWhile method will return only those items, for which lambda expression would return true. Also not that I could as easy replace the ToArray<string>() method at the end with ToList<string>() and return a generic list of strings:

List<string> months = cultureMonths.TakeWhile<string>(month => month.Length > 0).ToList<string>();

... but since this is most likely a read-only list, it doesn't really matter.

WLM tip: just paste the image to send it over

While conversing over Windows Live Messenger the other day, I became aware that not everybody knows about its feature to send an image over by simply pasting it into the message window. You know, instead of the lengthy process of pasting PrintScreen-ed image into Word or Paint, saving it into a file, then dragging the file into the message window, you can as well copy the image (PrintScreen or Windows Vista's Snipping tool) and paste it directly into WLM's message window. WLM will then automatically create a temporary file and send that over to the receiver...

There, a very quick and simple WLM tip :)

Make your application speak

.NET Framework 2.0 simplified the way of playing audio files from desktop applications. .NET Framework 3.0 takes this one step further by introducing the speech API, residing in the System.Speech namespace (it's basically a wrapper around Microsoft SAPI and is packed in System.Speech.Dll).

Using the SpeechSynthesizer class you can make your computer actually speak the text you feed to it:

SpeechSynthesizer synth = new SpeechSynthesizer();
synth.Speak("Hello world!");

If you don't want to stop your application from blocking the execution while speaking, this is there's the asynchronous equivalent to this method:

SpeechSynthesizer synth = new SpeechSynthesizer();
synth.SpeakAsync("Hello universe!");

The class provides a lot of ways of influencing the sound, like changing the rate, volume, providing hints on pronunciation, including existing sounds and changing the voice. Windows Vista comes with the preinstalled voice called Microsoft Anna, while Microsoft Sam should be available on Windows XP.

OK, so I thought I would update my You've got mail application sample by including some spoken text when new mail "arrives". This is the code I used:

PromptBuilder builder = new PromptBuilder();
builder.AppendAudio(new Uri(@"file://\windows\media\windows notify.wav"));
builder.AppendBreak(PromptBreak.Small);
builder.AppendText("You've got mail.");
builder.AppendBreak(PromptBreak.Small);
builder.AppendText("I think it's from your... wife.");

SpeechSynthesizer synth = new SpeechSynthesizer();
synth.SpeakAsync(builder);

And this is the extended You've got mail sample project for download.

Enjoy. A couple of notes though: The speech API does not require you to build a WPF to use it. You can also use it from Windows Forms or a Console application, just as long as you're targeting .NET FX 3.0. And don't forget to reference the System.Speech.Dll.

You've got mail

Paste as Xaml Visual Studio Add-In

Common Windows Presentation Foundation controls don't necessarily provide an intuitive path for upgrading from their Windows Forms equivalents. Take, for example, the RichTextBox control - there is no Rtf property for setting and getting RTF formatted text in WPF's RichTextBox. You can however, still load the RTF text into RichTextBox, using this method (loading RTF text from an embedded resource called MyRtfText):

ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytes = encoding.GetBytes(Properties.Resources.MyRtfText);

using (MemoryStream s = new MemoryStream(bytes))
{
   
TextRange range = new TextRange(rtfBox.Document.ContentStart, rtfBox.Document.ContentEnd);
   
range.Load(s, DataFormats.Rtf);
}

But how about creating a couple of text lines that would fit right into WPF's RichTextBox? RichTextBox exposes the Document property, which would accept a FlowDocument - and that's a native WPF content element, persisted in Xaml format. If you need to insert a piece of document into RichTextBox at design time, you'll have to know some Xaml to to it. Having to convert some existing text from RTF or other rich text format (pasting from Word seems like a good idea) requires a converter...

Luckily, such a converter is already built in WPF - it's the RichTextBox itself! The following snippet will stuff the text from the clipboard (text format doesn't matter, as long it's text) into the RichTextBox and get it out as a FlowDocument:

RichTextBox box = new RichTextBox();
box.Paste();

string text;
TextRange range = new TextRange(box.Document.ContentStart, box.Document.ContentEnd);

using (MemoryStream stream = new MemoryStream())
{
   
range.Save(TextDataFormat.Xaml.ToString());
   
stream.Seek(0, SeekOrigin.Begin);
   
using (StreamReader reader = new StreamReader(stream))
   
{
        text = reader.ReadToEnd();
   
}
}

And this is the core of this very simple Visual Studio 2008 Add-In that I've created - it will allow you to paste any text from the clipboard into Visual Studio as XAML.

Installing the Add-In is as easy as copying a DLL, included in the zip file [see link below], into *\My Documents\Visual Studio 2008\Addins folder and (re)start Visual Studio 2008. You'll find the new command under Tools menu.

image 

Download the Add-In. Full Add-In source code will follow...

On a side note... WPF future looks bright: performance and VS Designer improvements, new setup framework, new controls (DataGrid, Ribbon, Calendar, ...) See this ScottGu's post for more details.

Express your love with Silverlight :)

Want to impress your loved one with a Valentine's card tomorrow? Why not sending her/him a Silverlight Valentines? Silverlight and Windows Live teams created this card template for you to modify it and share your love. The process only takes four steps - you can pick a photo from either Windows Live Spaces or Flickr, enter a short text or poem, choose accompanying music and send the card.

image

A cool example of integrating other services with Silverlight... Just the right one to end up on CodePlex or MSDN Code Gallery someday ;)

Rethinking a mobile

With HTC out of the picture and iPhone on hold, there's a new mobile making a great entrance - Sony Ericsson just announced XPERIA™ X1! Windows Mobile (! a new direction for SE !), QUERTY keyboard + finger touch navigation on 800x480 display, 3.2MP camera and lots of connectivity options are just a few features, which make this phone jump way up high in the candidate list. The only question is - again - availability... "Available in “selected markets” from the second half of 2008"? Huh!