Updating the UI Thread in SL2

18 04 2008

Just as in WPF, Silverlight only allows you to update the UI from a UI Thread. This is done trough the Dispatcher object. There are a lot of samples floating around but none did exactly what I was looking for.

Let’s say we have the following code:

// Create a new thread and Start it

new Thread(new ThreadStart(() =>

{

    // Do some NON UI Asynchronous work here       

    PopulateSomeDataFromOtherData();

 

    // THIS WILL NOT WORK

    UpdateUI();

}

The code starts a new thread, then does some work on the thread. And when it’s finishes it tries to update the UI, this will fail!

To make this work, we need to tell the UI thread to execute this code trough the Dispatcher object:

First you define a custom (empty) delegate:

public delegate void UpdateUIDelegate();

And then you change the erroneous previous code to:

// Create a new thread and Start it

new Thread(new ThreadStart(() =>

{

    // Do some NON UI Asynchronous work here       

    PopulateSomeDataFromOtherData();

 

    // Define an action to execute in the UI Thread

    UpdateUIDelegate action = new UpdateUIDelegate(() =>

    {

        //Update the UI

        UpdateUI();

    });

 

    // Tell the UI Thread (Dispatcher) to execute the action

    Application.Current.RootVisual.Dispatcher.BeginInvoke(action);

})

).Start();

The changes use the Dispatcher from the RootVisual to execute the action delegate. This will nicely update the UI from a non UI-Thread.

NOTE: The Dispatcher object used in this sample is from the RootVisual. But every Control has it’s own Dispatcher object. Use it when it’s available, it will save you a lot of debugging.

For some more info on Silverlight and Threading check:

Stay in the light!

Robertjan Tuit

 



Silverlight 2 - MSN Video ListBox

9 04 2008

NOTE TO RSS READERS: Click this link to see the images and source code correctly.

This is just one of those days: I have been redoing my Silverlight project for 5 times now and tried about 10 ways to do the same thing. All resulting in nothing. Not the result I wanted and not an error, If I had any hair I would have pulled it out. But I guess the choice to go work with a beta product was my own.

Onto the real reason of this blog post: to prevent you from having the same terrible day. I was able to reproduce the error in a test project which will also demonstrate some nice features of SL that do work as expected :).

The end result

Usually I don’t begin with the end, but I always like to visualize what I’m going to make:

image

and we will be using a the Random MSN Video service as our data source:
http://catalog.video.msn.com/randomVideo.aspx?mk=us&vs=0&df=99&c=10

For the lazy (most of us developers/designers), here is the source code we are going to create:

New Project

We start out by creating a new Silverlight Project in this demo I assumed it to be named SilverlightApplication2:

image

And in the next screen select "Add a new Web to the solution for hosting the control" and select "Web Application Project".

image 

After the 2 projects are created, set SilverlightApplication2TestPage.aspx as your start page.

XML to Objects for Databinding

Silverlight does not yet support the direct XML databinding available in WPF. So we will have to do our binding by hand. First let’s create the data model we will be using: Add a new class "VideoFeedItem.cs" to the SilverlightApplication2 project with the following code:

public class VideoFeedItem

{

    public string Title { get; set; }

    public string Source { get; set; }

    public string PublishDate { get; set; }

    public string Description { get; set; }

    public string ImageUrl { get; set; }

    public string VideoUrl { get; set; }

    public string ViewCount { get; set; }

}

Then add a new class "VideoDS.cs" to the SilverlightApplication2 project, I have added code comments to explain what it does:

/// <summary>

/// This class will load from a webservice and

/// provide a datasource which we can bind to from XAML.

/// </summary>

public class VideoDS : INotifyPropertyChanged

{

    // Webservice URI & Namespace

    private const string _randomVideo = "http://catalog.video.msn.com/randomVideo.aspx?mk=us&vs=0&df=99&c=10";

    readonly XNamespace _NS = "urn:schemas-microsoft-com:msnvideo:catalog";

 

    // Bindable Collection

    public ObservableCollection<VideoFeedItem> RandomVideos { get; set; }

 

    public VideoDS()

    {

        // Only load the video feed when we are in the browser (Not in blend/VS)

        if (HtmlPage.IsEnabled)

            LoadVideoFeed();

    }

 

    /// <summary>

    /// Load the video feed and put it into our collection

    /// </summary>

    private void LoadVideoFeed()

    {

        // Use a normal webclient to fetch the feed

        var wc = new WebClient();

        // New lambda style delegate declaration

        wc.DownloadStringCompleted += (sender, e) =>

        {

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

            // Linq Select from the XML Tree and create a new VideoFeedItem for each selected.

            var videos =

              from video in doc.Descendants(_NS + "video")

              select new VideoFeedItem()

              {

                Title = (string)video.Element(_NS+"title"),

                Source = (string)(video.Element(_NS + "source").Attribute("friendlyName")),

                PublishDate = DateTime.Parse((string)video.Element(_NS + "startDate")).ToShortDateString(),

                Description = (string)video.Element(_NS + "description"),

                ImageUrl = GetUriAsset(video.Element(_NS + "files"), "file", "2007"),

                VideoUrl = GetUriAsset(video.Element(_NS + "videoFiles"), "videoFile", "1002"),

                ViewCount = (string)video.Element(_NS + "usage").Element(_NS + "usageItem").Attribute("totalCount"),

              };

 

            // Add the results to the Collection

            RandomVideos = new ObservableCollection<VideoFeedItem>();

            foreach (var video in videos)

                RandomVideos.Add(video);

 

            // Notify all listeners that the data has changed

            PropertyChanged(this, new PropertyChangedEventArgs("RandomVideos"));

        };

        wc.DownloadStringAsync(new Uri(_randomVideo));

    }

 

    #region LINQ Uri Helper

    /// <summary>

    /// Helps with the finding of some data in the complicated XML Structure

    /// </summary>

    private string GetUriAsset(XContainer element, string nodeName, string formatCode)

    {

        var uris = from file in element.Descendants(_NS + nodeName)

                                   where (string)file.Attribute("formatCode") == formatCode

                                   select (string)file.Element(_NS + "uri");

        return ((uris.Count<string>() > 0) ? uris.First<string>() : string.Empty);

    }

    #endregion

 

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

}

Binding

Now that we have setup the classes necessary for the data loading and binding, let’s add the ListBox to our page.xaml. Page.xaml should look like this:

<UserControl x:Class="SilverlightApplication2.Page"

   xmlns="http://schemas.microsoft.com/client/2007"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"             

   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"             

   xmlns:SilverlightApplication2="clr-namespace:SilverlightApplication2"

   mc:Ignorable="d"

   Width="600" Height="200">

    <UserControl.Resources>

        <SilverlightApplication2:VideoDS x:Key="VideoDS" d:IsDataSource="True"/>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">

        <ListBox ItemsSource="{Binding RandomVideos, 
                                Source
={StaticResource VideoDS}}"/>

    </Grid>

</UserControl>

You can now run the application, it should look like this:

image

Template

As you see here, the listbox has found our collection, but has no clue whatsoever what to do with it. To tell it how it should display our data, we add ListBox.ItemTemplate and we change the orientation using the ListBox.ItemsPanel property:

<ListBox ItemsSource="{Binding RandomVideos, Source={StaticResource VideoDS}}">

    <ListBox.ItemTemplate>

        <DataTemplate>

            <TextBlock Text="{Binding Title}"/> 

        </DataTemplate>

    </ListBox.ItemTemplate>

    <ListBox.ItemsPanel>

        <ItemsPanelTemplate>

            <StackPanel Orientation="Horizontal"/>

        </ItemsPanelTemplate>

    </ListBox.ItemsPanel>

</ListBox>

This should result in the following (with other data ofcourse since the video’s are random):

image

I’m always a big fan of the separation of design and behavior, so let’s move the properties to a style. First remove the properties and add a Style to the ListBox:

<ListBox Style="{StaticResource ListBoxStyle}" ItemsSource="{Binding RandomVideos, Source={StaticResource VideoDS}}"/>

Style

And then add a Style to the UserControl:

<UserControl.Resources>

    <SilverlightApplication2:VideoDS x:Key="VideoDS" d:IsDataSource="True"/>

    <Style x:Key="ListBoxStyle" TargetType="ListBox">

        <Setter Property="ItemsPanel">

            <Setter.Value>

                <ItemsPanelTemplate>

                    <StackPanel Orientation="Horizontal"/>

                </ItemsPanelTemplate>

            </Setter.Value>

        </Setter>

        <Setter Property="ItemTemplate">

            <Setter.Value>

                <DataTemplate>

                    <TextBlock Text="{Binding Title}" />

                </DataTemplate>

            </Setter.Value>

        </Setter>

    </Style>

</UserControl.Resources>

The above style does exactly the same thing as out previous properties does, so no changes in result here. As a design choice you could also add the Style to the Resources in the App.xaml.

Image Binding

Next we’ll add an Image to the mix. We’ll also add a StackPanel and some Margin to make it look a little bit better.

<Setter Property="ItemTemplate">

    <Setter.Value>

        <DataTemplate>

            <StackPanel Width="200">

                <TextBlock Text="{Binding Title}" HorizontalAlignment="Center" Margin="5,5,5,0"/>

                <Image Height="120" Stretch="Uniform" Source="{Binding ImageUrl}" HorizontalAlignment="Center" Margin="10,10,10,10"/>

            </StackPanel>

        </DataTemplate>

    </Setter.Value>

</Setter>

Build and run the project, it should look something like this:

image

UserControl in a Style

To get a little bit more control over the video, we are going to move the content of the <DataTemplate> to a User Control. Add a new Silverlight UserControl to the project with the name : VideoFeedItemControl.

Move the XAML from the <DataTemplate> to the new usercontrol:

<UserControl x:Class="SilverlightApplication2.VideoFeedItemControl"

   xmlns="http://schemas.microsoft.com/client/2007"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid x:Name="LayoutRoot">

        <StackPanel Width="200">

            <TextBlock Text="{Binding Title}" HorizontalAlignment="Center" Margin="5,5,5,0"/>

            <Image Height="120" Stretch="Uniform" Source="{Binding ImageUrl}" HorizontalAlignment="Center" Margin="10,10,10,10"/>

        </StackPanel>

    </Grid>

</UserControl>

And place the <VideoFeedItemControl> in the Page.xaml <DataTemplate>:

<Setter Property="ItemTemplate">

    <Setter.Value>

        <DataTemplate>

            <SilverlightApplication2:VideoFeedItemControl/>

        </DataTemplate>

    </Setter.Value>

</Setter>

Ready to go, build and run. Let’s see our end result:
image
Hey, wait a minute!? that’s not what we were aiming for. That’s empty!

We did not get any errors, everything seems to be working correctly, what happened here?

The error

This was the point where it got frustrating. It took me more than a day to figure out. Remember the namespace handling in the page.xaml? One of these was a reference to our own project. This was generated automaticaly.

I’m talking about this line:

xmlns:SilverlightApplication2="clr-namespace:SilverlightApplication2"

Nothing wrong with it, right?

If you know what the problem is, the fix is very simple. Add:
assembly=SilverlightApplication2.

It should now be:

clr-namespace:SilverlightApplication2;assembly=SilverlightApplication2

We build and we get:

image

That looks more like it!

So we only needed an assembly reference to the current assembly? Strange behavior.

I’m still looking for the reason, but at least it is fixed. The strangest thing is that if you would move the UserControl back to the normal page. The UserControl works normally without the need of the assemblyname= in the namespace declaration.

So it seems this only happens when a UserControl is used within a template or style declaration.

Would be nice to have

Ofcourse it is much more work to have running video’s in the listbox. And there are at least 20 more things I can think of that could nicely extend the sample.

Maybe next time :)

Stay in the light!

Robertjan Tuit

Technorati tags: ,


Silverlight Multiplayer Pokerroom

  • nederlands
22 02 2008

Finally, after a few weeks of very hard work I’m back.

The last few weeks were about my Silverlight Multiplayer Pokerroom, a technical showcase that tries to show what can be done with Silverlight 1.1/2.0 and Silverlight Multiplayer PokerRoomASP.NET 3.5.

An application, with multiple poker tables. In which users on different computers, on different sides of the world, can play poker and chat with each other.

And when there is no one around to play with you can always add a "bot". (Type /help in the chat for more info).

You do have to create your own account before you can start playing. But because it only requires you to enter a username, password and e-mail address, this should take you no time at all.

It has been tested to work on IE6+7 and Firefox on windows.

Some of the more advanced poker rules are not implemented (sidepots, all-in, etc…),  so expect it to behave strangely when this happens.

It still contains a few bugs, that is why the application is recycled every 120 minutes.

The game should keep you busy for a while and hopefully it will get some people "into the light " ;-).

Design & 2.0

Silverlight Multiplayer PokerRoomI’m in the process of getting a real designer to redesign the pokerroom, and in a few weeks (probably after Mix) the application has to be made compatible with Silverlight 2.0.

More suggestions are always welcome, please use the contact form. I’ll keep you all posted on the progress.

Geek

As a true geek, there are is some technical stuff I would like to highlight:

  • There is a real PokerHand comparer that can compare 11 billion hands per second ;-), totally useless of course, but just as fun.
  • The webservice calls are long running. Meaning that as long as there is no new data, they stay open and sleep. A very simple but effective way to minimize webservice calls. Hopefully I can replace this with a nice WCF solutions in 2.0.
  • The colors in the chatbox, were a hell of a job, but just look nice!.
  • When the server restarts or when the session goes away, the client app will recognize and restart itself.
  • The bot’s taunt you when they win money from you ;-)  (Altough it would be nice in the future if they used more than one taunt)

Links

Have fun playing poker, and see you at Mix!

Robertjan Tuit



Mix08

  • nederlands
1 02 2008

It has been some time ago that I have seen the inside of Windows Live Writer. I have been terribly busy with a project for the Silverlight Challenge en currently still am. This is why I haven’t blogged as much is I usually do. Also the previously promised report about the Envision-Event trip will have to wait.

Why this blog post then, U ask? I would like to share with you the joy of having registered for the Mix08 in Vegas. An event you should not miss this year.

With the release of  Silverlight 2.0 (beta) and subjects as IE8, ASP.NET MVC, IIS7, WPF 3.5, Dynamic Data Controls and.NET 3.5, I’m very much looking forward to it.

And the fact that it is in Las Vegas is not bad either. I haven’t settled yet on the flying schedule, and the hotel.

Who else is going? and if you are, how did you arrange your flight schedule and your hotel, any tips that can help me? The Venetian is a bit to pricey for my taste.

Going to dive back into my Silverlight 1.1 Alpha project. The longer I work with it the more I’m looking forward to the 2.0 beta release.

Hope to see you in Vegas!

Robertjan Tuit



Silverlight CustomControls and Blend 2

  • nederlands
26 12 2007

Most of you would have probably stopped developing in silverlight 1.1 2.0 after seeing how custom controls worked in blend 2 (they do nothing). But for those of you who persevered some tips to help you on your way.

Xaml

The current control model is absolutely unfinished. One of the firts thins you have to do is change the way a CustomControl is loaded, and map the controls in your xaml to your code.

System.IO.Stream s =
  this.GetType().Assembly.GetManifestResourceStream(“UserControl1.xaml”);
FrameworkElement _actualControl = this.InitializeFromXaml(
  new System.IO.StreamReader(s).ReadToEnd()
);
_actualControl.FindName(“Button”);Namespaces

Blend 2 doesn’t understand it when you put namespaces in your customcontrol xaml, it does work in the xmlns decleration but not in the actual xaml control.

Wrong:
<CustomControls: Buttons.RoundButton …..=“” /> and
<CustomControls.Buttons: RoundButton …..=“” />

Right:
<CustomControls:RoundButton …..=“” />

Visual Containers

Because custom controls do not show in blend 2, making layouts is a very dificult story. One solution is to create rectangles for every custom control and name them the same except for a temp_ prefix.

Then in the onloaded event of your page, cycle trough your object tree and place the custom controls over the rectangles and remove them.

More to come.

Robertjan Tuit



Wiinority Report

  • nederlands
22 12 2007

Sometimes i am so inspired by things i read, see or hear, that i am not quite sure how to act on them. But i’m glad that have my Blog these days to at least share it with you all.

That we can connect our wiimote to our pc is not new, but what this guy is doing with it is realy refreshing and inspiring.

The principle behind a wiimote is a camera inside the wiimote that registers the 2 light sources inside you sensor bar on top of your tv. Bu what if you swap them: You place the wiimote on top or at the bottom of you tv and you move the light sources around, the applications are very endless. For example when you use a pair of glasses with 2 lights on eather side.

Especially his 3D viewport implementation is inspiring and the other makes the input devices from Minority Report science fact instead of function!

Everything is available as c# source code, i can’t wait to get them to work on my own laptop!

Link : http://www.cs.cmu.edu/~johnny/projects/wii/

Video’s :



Volta, Web Development 2.0

7 12 2007

Inderdaad: Web Development 2.0 en niet Web 2.0.

Ik ben echt ontzettend enthousiast over wat er vandaag uit de Microsoft Labs is geslopen, dus neem alsjeblieft de tijd om deze lange post door te lezen. Ik ga proberen uit te leggen wat Volta nu precies is, om daarmee ook volta_thumbnail aan te geven waarom ik het zo geweldig vind.

Voor de mensen die mijn blog al wat langer lezen, Volta is Script# in het kwadraat. Volta werkt alleen niet met source code maar met MSIL (Intermediate language). Deze MSIL kan hij dan weer converteren (hercompileren) naar javascript dat draait in elke willekeurige browser en elk willekeurig platform (in deze ctp alleen nog IE en FF). Het genereren van cross browser javascript kan je vele uren ontwikkel en debug tijd schelen.

Je kan dus “gewoon” C# (en o.a ook VB, Python en Ruby) code schijven tegen je html pagina aan. Dus als je in html een element met id=”Text1″ hebt, dan kun je in C#  Text1.InnerHtml = “Nieuwe tekst”; intikken, waarbij het bij het hercompileren door Volta, vertaald zal worden naar javascript en uitgevoerd in de browser.

Tot aan hier, nog niets nieuws. Want dit konden we al met Script#. Hoewel deze implementatie je wel behoorlijk veel meer vrijheid geeft. De echte kracht van Volta zit hem wat mij betreft in het feit dat je binnen een project zowel server als client code kan schrijven.

image001

Deze laag splitsende technologie (zie ook plaatje hierboven) werkt door middel van attributen (o.a. [RunAtOrigin]) die bepaalde classes op de server en andere classes op de client laten draaien. Deze classes kunnen dan, zonder dat je daar zelf code voor hoeft te schrijven, elkaar aanroepen alsof ze zich op dezelfde laag bevinden. Volta genereert alle code die nodig is voor de communicatie tussen de browser en de server.

Daarbovenop levert volta een wijde reach van tools en functionaliteit (o.a. controls en javascript interop). Daarme tilt Volta het ontwikkelen van webapplicaties naar een nieuw niveau.

Wel moet op dit moment worden aangetekend dat het wel te maken hebben met een CTP preview release waarvan de functionaliteit nog lang niet vast staat en de code nog lang niet productie klaar is, maar een kijkje in de keuken van de toekomst is natuurlijk nooit verkeerd.

Dus als je net zoals ik gegrepen bent door het Volta Virus, kun je de volgende links volgen om meer informatie te krijgen en er zelf mee aan de slag te gaan en ik hoor net dat Christiaan van Bergen na het weekend met een paar mooie code voorbeelden komt om je verder te helpen.

Robertjan Tuit

p.s. Waar zouden ze toch dat logo vandaan hebben ?



Outlook Inbox Search : Xobni

5 12 2007

Een van mijn dagelijkse irritaties is de manier waarop outlook met mijn e-mail archief omgaat, even snel wat opzoeken is een crime. Een goed overzicht kan je al helemaal vergeten, zelfs met “search folders” kan je er nog eigenlijk niet veel mee.

Dan heb je natuurlijk Live Search, waar de door Microft opgekochte Lookout inzit, maar die wil ik helemaal niet!. Zeker omdat je er automatisch ook de harddisk indexer en andere troep bijkrijgt, en spreek me al helemaal niet over het zoek panel (ctrl-f) wat mijn standaard explorer zoek paneel vervangt.Xobni, Inbox 2.0

Daarom ben ik al maanden op zoek naar een goede zoek tool voor Outlook 2007. En vorige week kwam ik er eindelijk een tegen die we me aansprak, waarbij de user interface van deze applicatie alleen, al het vermelden waard is : Xobni, Inbox 2.0.

Xobni (Inbox omgekeerd) is veel meer dan een zoek tool maar maar het lijkt erop dat het, als het al zijn beloftes waarmaakt, in ieder geval mijn dagelijks e-mail leven een stuk gaat vermakkelijken.

Heel kort door de bocht kan je ermee zoeken, snel oude e-mails vinden en heel snel springen tussen verschillende contacten die je niet eens hoeft toe tevoegen als contact. Maar dat geeft bij lange na niet weer welke potentie het heeft, daarvoor moet je het zelf in actie zien : “Feature list & Video“.

Kortom, een “must have” voor iedereen die veel e-mail verstuurd en ontvangt en dan laat ik de geweldige user interface nog even achterwege.

Er zit natuurlijk wel een nadeel aan : Hij is nog niet gereleased en alleen beschikbaar in een closed beta. Please let me in!

Link : www.xobni.com 
Features & video : http://www.xobni.com/learnmore/
Blog : www.xobni.com/blog

Robertjan Tuit



Released : Visual Studio 2008, .NET 3.5 & Ajax Control Tookit

20 11 2007

Ik in ieder geval, en ik denk een aardig aantal mensen met mij, zit al een tijdje op dit nieuws te wachten. En vandaag is het zover , de RTM van Visual Studio 2008, Team Foundation Server 2008 en .NET 3.5.

Te downloaden via :

Let wel op: de Silverlight 1.1 Alpha en Web Deployment Add-Ins werken NOG NIET met deze release, deze hopen ze de komende weken beschikbaar te maken.

Een korte feature list van VS2008 :

VS2008 is ontwikkeld met TFS. Channel 9 heeft een video met Somasager over dit onderwerp : Channel9 VS 2008 Built with TFS Talk 

Daarnaast heeft het Ajax Control Tookit team besloten om hun nieuwe release ook samen te laten hangen met de Visual Studio 2008 Release. Die kun je hier vinden : Nieuwe Ajax Control Tookit Release (11119 release)

Bron : De enige echte Scott Guthry natuurlijk, en Somasegar voor de TFS video.

Robertjan Tuit



Gratis ASP.NET Ajax Rich Text Editor Control

12 11 2007

iets wat in zo’n beetje elke website wel terugkomt is richt text editng. Tot nu toe moest je er of zelf een schrijven of er een kopen. Nu hoeft dat niet meer!

Kannan Sundarajan heeft een hele aardige gemaakt en deelt hem met ons op codeplex zodat we hem kunnen hergebruiken.

Ik heb hem al even in wat voorbeelden gehangen die ik hier had liggen en het lijkt allemaal heel goed te werken, bedankt Kirti!

Demo : live demo site!
CodePlex: http://www.codeplex.com/rte/
Blog : Kirti’s blog

Robertjan Tuit