Dear visitor, thanks for stopping by! If you want, you can follow all updates on Snowball.be via RSS. You can also follow me on Twitter or Facebook. More interesting posts from other Microsoft Regional Directors can be found at The Region.
Gill Cleeren     Silverlight | sl4     January 18, 2011    

The Silverlight exam (70-506) is being released soon. Together with the people of SilverlightShow, I decided to create a guide to help with the exam preparation. The first part is online now, you can find it here.

image

  Posted on: Tuesday, January 18, 2011 10:58:07 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     mvvm | Silverlight | sl4     December 31, 2010    

When working with MVVM, the Command pattern is used to bind actions (such as a Click on a Button) in the View with commands in the ViewModel. The ICommand interface in Silverlight has 3 members:

// Summary:
//     Defines the contract for commanding, using the same contract as used in WPF.
public interface ICommand
{
    // Summary:
    //     Occurs when changes occur that affect whether the command should execute.
    event EventHandler CanExecuteChanged;
 
    // Summary:
    //     Defines the method that determines whether the command can execute in its
    //     current state.
    //
    // Parameters:
    //   parameter:
    //     Data used by the command. If the command does not require data to be passed,
    //     this object can be set to null.
    //
    // Returns:
    //     true if this command can be executed; otherwise, false.
    bool CanExecute(object parameter);
    //
    // Summary:
    //     Defines the method to be called when the command is invoked.
    //
    // Parameters:
    //   parameter:
    //     Data used by the command. If the command does not require data to be passed,
    //     this object can be set to null.
    void Execute(object parameter);
}

The fact whether or not the command can be executed (read: a Button is enabled or not) depends on the boolean value returned by the CanExecute. By default, this value is evaluated on first load of the View: a Save button should initially be disabled. However, during user input, this value has to be re-evaluated: after the user has filled in a field, we need to check if the Save button should be enabled. For this purpose, the CanExecuteChanged event exist. This event should be raised whenever the value of CanExecute should be evaluated once again.

In MVVM Light, the lightwork MVVM framework by Laurent Bugnion, a method called RaiseCanExecuteChanged exists on the RelayCommand class for this very purpose. Let’s take a look at how we can use this method.

I have a very basic view, containing some TextBox fields. Note that initially, the Save button is disabled:

image

The XAML code is shown below. The fields are bound to a Person object, that I expose in the ViewModel (shown further).

 
<Grid Width="450">
    <Grid.RowDefinitions>
        <RowDefinition Height="50"></RowDefinition>
        <RowDefinition Height="40"></RowDefinition>
        <RowDefinition Height="40"></RowDefinition>
        <RowDefinition Height="40"></RowDefinition>
        <RowDefinition Height="40"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock x:Name="FirstNameTextBlock" Grid.Row="1" 
        Grid.Column="0" Text="First name" VerticalAlignment="Center" Margin="3"></TextBlock>
    <TextBlock x:Name="LastNameTextBlock" Grid.Row="2" 
        Grid.Column="0" Text="Last name" VerticalAlignment="Center" Margin="3"></TextBlock>
    <TextBlock x:Name="EmailTextBlock" Grid.Row="3" 
        Grid.Column="0" Text="Email" VerticalAlignment="Center" Margin="3"></TextBlock>
    <TextBox x:Name="FirstNameTextBox" Grid.Row="1" 
        Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Width="200" 
        Margin="3" Text="{Binding Person.FirstName, Mode=TwoWay}"></TextBox>
    <TextBox x:Name="LastNameTextBox" Grid.Row="2" Grid.Column="1" 
        VerticalAlignment="Center" HorizontalAlignment="Left" Width="200" 
        Margin="3" Text="{Binding Person.LastName, Mode=TwoWay}"></TextBox>
    <TextBox x:Name="EmailTextBox" Grid.Row="3" Grid.Column="1" 
        VerticalAlignment="Center" HorizontalAlignment="Left" Width="200" 
        Margin="3" Text="{Binding Person.Email, Mode=TwoWay}"></TextBox>
    <Button Content="Save"  Grid.Row="4" Grid.Column="1" 
        Command="{Binding SaveCommand}" VerticalAlignment="Center" 
        HorizontalAlignment="Right"></Button>
</Grid>

The ViewModel called MainPageViewModel is set as the DataContext for this View. This ViewModel exposes a Person instance (a Model class) and a RelayCommand for the View to bind to.

public class MainPageViewModel: ViewModelBase
{
    public Person Person { get; set; }
 
    public RelayCommand SaveCommand { get; set; }
 
}

The SaveCommand is initialized as follows:

private void InitializeCommands()
{
    SaveCommand = new RelayCommand(OnSave, OnCanSave);
}
 
private void OnSave()
{
    //Perform save to database
}
 
public bool OnCanSave()
{
    return !string.IsNullOrEmpty(Person.FirstName) 
        && !string.IsNullOrEmpty(Person.LastName) 
        && !string.IsNullOrEmpty(Person.Email);
}

Note that the OnCanSave (the implementation of the CanExecuteChanged) will at this point only be called upon binding of the ViewModel. However, I need this to be evaluated every time a value of the bound Person changes: only after all 3 fields have a value, the Save should be enabled.

To implement this, I changed the Person class as follows. It implements the INotifyPropertyChanged interface.

public class Person : INotifyPropertyChanged
{
    private string _firstName;
    private string _lastName;
    private string _email;
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    public string FirstName
    {
        get
        {
            return _firstName;
        }
        set
        {
            if (_firstName != value)
            {
                _firstName = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
                }
            }
        }
    }
 
    public string LastName
    {
        get
        {
            return _lastName;
        }
        set
        {
            if (_lastName != value)
            {
                _lastName = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("LastName"));
                }
            }
        }
    }
 
    public string Email
    {
        get
        {
            return _email;
        }
        set
        {
            if (_email != value)
            {
                _email = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Email"));
                }
            }
        }
    }
}

In the constructor of the ViewModel, I register for the PropertyChanged event being raised from the Person model.

public MainPageViewModel()
{
    InitializeCommands();
 
    Person = new Model.Person();
    Person.PropertyChanged += 
        new System.ComponentModel.PropertyChangedEventHandler(Person_PropertyChanged);
}

In this event handler, I now call the RaiseCanExecuteChanged method, part of the RelayCommand class of MVVM Light.

void Person_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    SaveCommand.RaiseCanExecuteChanged();
}

This causes the CanExecuteChanged to be raised, causing Silverlight to evaluate again if the Command should be enabled or not. In this particular case, I do this as follows (this code was already shown and executed also on the initial binding):

public bool OnCanSave()
{
    return !string.IsNullOrEmpty(Person.FirstName) 
        && !string.IsNullOrEmpty(Person.LastName) 
        && !string.IsNullOrEmpty(Person.Email);
}

Whenever a value is provided for all 3 fields, the Button will be enabled.

image

  Posted on: Friday, December 31, 2010 11:19:12 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     Silverlight | sl4     December 19, 2010    

Since Silverlight 3, we have had the Navigation Application template available. Using this template, we did not need any tricks anymore to do navigation between “pages” (which did not exist in Silverlight 2, we only had the UserControl). In SL3, a Navigation Application was however rather locked down: developers had little to none options available to hook into the navigation process itself.

With Silverlight 4, the INavigationContentLoader interface was introduced. This interface provides a means for us to override how the navigation framework works: we can provide our own logic for the page-loading process. Based on the target URI that is passed in, we can load the page, but we can do other actions as well first. Let’s first look at this interface:

public interface INavigationContentLoader
{
    IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, 
        AsyncCallback userCallback, object asyncState);
    
    void CancelLoad(IAsyncResult asyncResult);
   
    bool CanLoad(Uri targetUri, Uri currentUri);
    
    LoadResult EndLoad(IAsyncResult asyncResult);
}

Because we can provide whatever functionality we want, this simple interface does much more, we can practically do whatever we want when a user clicks on a link. Think of actions such as the following:

  • The target URI could contain the name of the XAP file in which the XAML view can be found (ex. MyXap.xap/View1.xaml). Our custom logic could check if this XAP file is already available/downloaded on the client. If not, it can be downloaded on-demand.
  • Check that the user has permissions to see the requested URL.
  • Load the ViewModel corresponding to the View that is navigated to.
  • Pass parameters to the constructor of a page

The flow to load a page (and the corresponding calls can be seen in the interface):

  • A check is done using the CanLoad method if the requested page can be found. This can be a location to handle in our own way how errors resulting from navigating to a non-existing page are shown to the user.
  • The page loading process is using a cancellable asynchronous way to load pages, starting with the BeginLoad. In the BeginLoad, we, quite logically, start the loading process.
  • Once BeginLoad started the loading process, the navigation framework waits for the loading to be complete. Once complete, the Endload is called. In normal circumstances, the LoadResult is a fully initialized Page that can now be displayed to the user.

Let’s now look at a small sample. Assume we have a service that returns, based on the role name of the logged-in user, a list of pages the user has access to.

 

[OperationContract]
public List<SitePermission> GetAccesiblePages(string roleName)
{
    switch (roleName)
    {
        case "user":
            return new List<SitePermission>() 
            {
                new SitePermission(){PageName="/Views/Home.xaml",Allowed= true},
                new SitePermission(){PageName="/Views/About.xaml",Allowed= true},
                new SitePermission(){PageName="/Views/Products.xaml",Allowed= true},
                new SitePermission(){PageName="/Views/Admin.xaml",Allowed= false}
            };
            case "administrator":
            return new List<SitePermission>() 
            {
                new SitePermission(){PageName="/Views/Home.xaml",Allowed= true},
                new SitePermission(){PageName="/Views/About.xaml",Allowed= true},
                new SitePermission(){PageName="/Views/Products.xaml",Allowed= true},
                new SitePermission(){PageName="/Views/Admin.xaml",Allowed= true}
            };
            default:
            return new List<SitePermission>() 
            {
                new SitePermission(){PageName="/Views/Home.xaml",Allowed= false},
                new SitePermission(){PageName="/Views/About.xaml",Allowed= false},
                new SitePermission(){PageName="/Views/Products.xaml",Allowed= false},
                new SitePermission(){PageName="/Views/Admin.xaml",Allowed= false}
            };
    }
}

In our Silverlight code, we download this list upon start of the application and which each navigation action, we check if the target URI is allowed to be accessed by the user. Because we want to do this using the navigation application template, we need to write a custom implementation of the page loading.

To do this, we start by adding a class that implements the INavigationContentLoader interface.

public class AutorizedPageContentLoader:INavigationContentLoader
{
    ...
}

To keep things simple initially, we’ll use the default instance for the page loading process, we’ll only change the CanLoad implementation. In the CanLoad, we need to access the list of SitePermissions, downloaded from the service. The following code is the service call, which was placed here in the App.xaml.cs (could be placed in a custom bootstrapper as well):

public ObservableCollection<SitePermission> SitePermissions { get; set; }
 
private void Application_Startup(object sender, StartupEventArgs e)
{
    LoadSitePermissions();
}
 
private void LoadSitePermissions()
{
    AuthorizedPageService.AuthorizedPageLoadServiceClient client = 
        new AuthorizedPageService.AuthorizedPageLoadServiceClient();
    client.GetAccesiblePagesCompleted += (s, e) =>
    {
        SitePermissions = e.Result;
        this.RootVisual = new MainPage();
    };
    client.GetAccesiblePagesAsync("user");
}

The CanLoad now checks this list and returns true or false based on the requested Uri.

public bool CanLoad(Uri targetUri, Uri currentUri)
{
    var item = ((App)Application.Current).SitePermissions.
        Where(s => s.PageName == targetUri.ToString()).FirstOrDefault();
 
    if (item != null)
    {
        return item.Allowed;
    }
 
    return false;
}

The BeginLoad, EndLoad and CancelLoad can be handled using the default instance of the page loading process:

private PageResourceContentLoader _loader = new PageResourceContentLoader();
 
public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, 
    AsyncCallback userCallback, object asyncState)
{
    return _loader.BeginLoad(targetUri, currentUri, userCallback, asyncState);
}        
 
public void CancelLoad(IAsyncResult asyncResult)
{
    _loader.CancelLoad(asyncResult);
}
 
public LoadResult EndLoad(IAsyncResult asyncResult)
{
    return _loader.EndLoad(asyncResult);
}

The final thing we need to do is of course making sure that our content loader implementation is used by the navigation frame.

 

 
<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}" 
    Source="/Home" Navigated="ContentFrame_Navigated" 
    NavigationFailed="ContentFrame_NavigationFailed">
    <navigation:Frame.UriMapper>
        <uriMapper:UriMapper>
            <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
            <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
        </uriMapper:UriMapper>
    </navigation:Frame.UriMapper>
    <navigation:Frame.ContentLoader>
        <local:AutorizedPageContentLoader></local:AutorizedPageContentLoader>
    </navigation:Frame.ContentLoader>
</navigation:Frame>

When the user now navigates to the Admin page (which is not allowed), the navigation will not be allowed.

clip_image002

  Posted on: Sunday, December 19, 2010 12:20:17 PM (Romance Standard Time, UTC+01:00)   |   Comments [1]
         
Gill Cleeren     Events | Silverlight | sl4     December 16, 2010    

Yesterday, I did another webinar for SilverlightShow titled “Building a Silverlight application end-to-end”. During the presentation (which took about 90 minutes), we had over 200 people attending which was great!

The goal of the presentation was giving an overview of topics that developers will encounter when building real world applications with the Silverlight platform:

  1. SketchFlow
  2. WCF RIA Services
  3. Data binding & DataGrid
  4. MVVM
  5. MEF
  6. Commanding & behaviors
  7. Messaging, navigation & dialogs
  8. Custom controls & third party controls
  9. OOB
  10. Printing

A video will be available shortly, meanwhile, you can already download the slides and demos here:
Slides - Demos

  Posted on: Thursday, December 16, 2010 9:32:39 AM (Romance Standard Time, UTC+01:00)   |   Comments [3]
         
Gill Cleeren     Events | Silverlight | sl4 | Speaking     October 27, 2010    

On Wednesday October 27th, I gave a webinar for SilverlightShow.net. The topic in this webinar was 10 tips in Silverlight 4. The video will be online soon. Meanwhile, you can already take a look at the slides and demos below.

SlidesDemos

  Posted on: Wednesday, October 27, 2010 10:23:57 PM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     Efficiency | Silverlight | sl4     October 25, 2010    

Light up your Silverlight skills with the all-new Global Silverlight Firestarter!

SLFirestarter_300X250

What is the Silverlight Firestarter?

-          An Event: A one day, global, live streamed and on demand event keynoted by Scott Guthrie

-          Training: New self-paced labs and walk through videos

-          Interactive: Got questions? Get your answers! Watch live and ask the Silverlight product team questions during the event.

-          Why Silverlight? Silverlight is Microsoft’s strategic development platform for building interactive applications across desktop, phone, and the browser.

Something for Everyone

-          Just starting out with Silverlight? Watch our On-Ramp sessions and work on hands on labs to get you started.

-          Already Building business applications? Watch the event live and learn how to create compelling business applications with Silverlight.

-          Got questions? Engage with the Silverlight product team live or in person with our interactive chat.

When
Register
How Much?

December 2, 2010 8am to 5pm PT
Register Online, Now!
Nothing! This is a free event

After the live event keep fueling the fire!

Dive deeper with additional hands on labs and videos that build on the live session content, accelerating you ahead of the crowd.

-          Watch the entire event on demand!

-          Plus, new self-paced labs and walk through videos

-          On Ramp Labs (100 level)

  • Hands on labs specifically focused on helping new developers get up to speed quickly on Silverlight
  • Do you know WinForms? HTML? ASP.NET? Want to learn Silverlight? We have a lab for you!

-          Building Better Business Apps (200-300 level)

  • Hands on labs focused on taking advantage of Silverlight to build real world business applications
  • Apply Data Strategies, Patterns, Out of Browser, RIA Services, and much more using Silverlight

-          Turnabout is fair play! Watch a video of our experts doing the labs themselves.

F I R E S T A R T E R     L I V E     A G E N D A

8:00 am
Silverlight Firestarter Keynote
Scott Guthrie

9:00 am
Masterful Data Strategies with Silverlight and WP7
Jesse Liberty

10:00 am
15 minute break

10:15 am
Roll Out Your Business Apps Today with RIA Services
Pete Brown

11:15 am
MVVM: Why and How? Tips and Patterns using MVVM and Service Patterns
John Papa

12:15 pm
Lunch break

1:00 pm
Silverlight Today and Tomorrow (Special Guest Panel)
Panel

1:30 pm
Building Real World Silverlight Apps
Tim Heuer

2:30 pm
15 minute break

2:45 pm
Tune Your Application: Profiling and Performance Tips
Mike Cook & Jossef Goldberg

3:45 pm
Killer Performance Tips for Silverlight Windows Phone 7
Jaime Rodriguez

After Party!

Spread the Word!

-          Blog and tweet to spread the word about the Firestarter!

-          Ask people to add the Twitter hash tag #slfs10 to their tweets

-          Use the banners and blog bling (attached)

Questions

Got questions? Ask slfs@microsoft.com

  Posted on: Tuesday, October 26, 2010 12:04:35 AM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     Efficiency | Silverlight | sl4 | Speaking     October 25, 2010    

This Wednesday, on October 27th, I’ll be doing another webinar for SilverlightShow.net. Like always, these are free to attend. The topic for this webinar is “10 Tips in Silverlight”. If you attend, you can win a copy of my book, Silverlight 4 data and services cookbook (which keeps getting great reviews by the way :) ).

The tips that you’ll see are the following:

  1. Behaviors
  2. PathListBox
  3. Binding tricks
  4. INavigationContentLoader
  5. Debugging services
  6. Securing service communication
  7. Leveraging ASP.NET membership
  8. Uploading and downloading files
  9. Downloading functionality on-demand
  10. Bag of tricks

Registration is free but required, you can register here.

  Posted on: Monday, October 25, 2010 11:47:24 PM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     .net 3.5 | .NET 4 | Efficiency | Silverlight | sl4     October 11, 2010    

After some time, I’m glad to announce that the official, world-renowned Silverlight Tour is coming to Belgium, the Netherlands, the UK and more countries, organized by Ordina Belgium. The second thing I’m glad about is that I’ll be the instructor for this training!

SilverlightTour

The most important link for all this: http://bit.ly/SilverlightTour, where you can find all information, registration and prices. Currently, we have an early bird offering ending in a few weeks for the first batch of sessions.

What is Silverlight Tour?

The Silverlight Tour Workshop is a three-day course on Silverlight 4, given all around the world throughout the USA, Asia and South-America. Ordina will organize the training in several European countries starting Q4 2010.

The training divides the content into three distinct areas: Design, Development and the Server-Side. Students should be able to develop Silverlight 4 applications once attending the workshop. The Workshop is structured with a mix of didactic lessons, demonstrations and hands-on labs.

Each student will leave the workshop having created several small Silverlight applications. This variety of learning techniques will ensure that all students become proficient in the technology quickly and in an exciting way.

Key values of Silverlight Tour

  • Learning Silverlight from an expert in the technology
  • Hands-on labs with Visual Studio and Blend make sure you get to apply your acquired knowledge
  • Architect Silverlight applications
  • Learn about LOB features such as data access and data binding

Why Silverlight?

Silverlight is Microsoft's approach to building RIA (Rich Internet Applications). The platform has since its introduction, taken the world by storm. Now at its fourth iteration, Silverlight is ready for building Line-Of-Business applications, building on the strong foundation of .NET.

Now is the time to learn Silverlight! Not only is Microsoft investing heavily in the platform, but Silverlight is also the base for Windows Phone 7, Microsoft's new mobile platform. And with WPF as the desktop variant, you can apply your knowledge on the web, on the desktop and on mobile devices.

The Silverlight Tour can help you achieve the knowledge you need to start building Silverlight applications today!

Our offering

The Silverlight Tour comes in 2 flavors, depending on your Silverlight knowledge.

If you don't have any experience with Silverlight yet, the Silverlight 4 Tour workshop is ideal for you. In this 3 day course, we are starting from scratch, teaching you the foundation for your Silverlight endeavours. After this training, you'll feel comfortable with the technology and can start building your own applications.

If you already have some experience with the platform, or you just followed the Silverlight 4 Tour, we advise you the Advanced Silverlight 4 workshop. In this 2 day training, we'll tackle the more advanced concepts such as MVVM, advanced data access and IOC.

We offer the combined course (Silverlight 4 Tour Workshop + Advanced Silverlight 4 workshop) at a reduced price.

  Posted on: Monday, October 11, 2010 3:10:14 PM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     Efficiency | Events | Silverlight | sl4 | Speaking     October 11, 2010    

Yesterday, I arrived back home after touring Sweden for a week. I gave presentations in Malmö, Stockholm, Örebro and Götherborg. Each session was attended by a great number of developers, all members of Swenug. The sessions were sponsored by the people at Telerik: at each session, I got to give away some cool prices from Telerik, including in each city a Telerik Ultimate Collection!

Malmo pictures

IMG_0405 IMG_0406

Stockholm pictures

IMG_0407 IMG_0408 IMG_0409 IMG_0410

Örebro pictures

IMG_0422 IMG_0423 IMG_0424 IMG_0425 IMG_0426 IMG_0427

Göthenburg pictures

IMG_0438 IMG_0440 IMG_0441 IMG_0442 IMG_0443 IMG_0444 IMG_0445 IMG_0446

In the meantime, here are the downloads for the sessions, including all demos and slide decks.

I hope to be back in Sweden very soon! If you have any questions or remarks, please let me know!

  Posted on: Monday, October 11, 2010 2:58:33 PM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     .NET 4 | Efficiency | ppt | Silverlight | sl4 | Speaking     September 29, 2010    

Yesterday, I gave a presentation at ReMix 2010 in Belgium, the third edition of this annual Microsoft event. My talk, Building an end-to-end Silverlight 4 application – Writing your Christmas Cards with Silverlight, was focused around the new and existing features in Silverlight 4, helping developers building Silverlight Line-Of-Business applications. These included data access, data binding, hardware access, drag and drop, right-clicking, Out-Of-Browser and Trusted applications.

The slide deck can be downloaded here and the entire demo can be found here.

  Posted on: Wednesday, September 29, 2010 10:20:40 AM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     Community | Events | Silverlight | sl4 | Speaking     September 24, 2010    

From October 4th until October 8th, I’ll be touring through Sweden, visiting 4 user groups in 4 cities to do a mini-Silverlight roadshow. During the 4 evenings, I’ll be giving sessions on data-related stuff using Silverlight.

If you’re in the neighborhood (or live in Sweden :) ), you’re welcome to join of course. All events are free and start at 6pm. Here are the details of where I’ll be on which day:

October 4th: Malmö
Registration: http://www.swenug.se/events/skaane-silverlight-4-tour-de
Address:
Cornerstone Malmö, 
Norra Vallgatan 100
Malmö

October 6th: Stockholm
Registration: http://www.swenug.se/events/sthlm-silverlight-4-tour-de
Address:
.Net Akademien
Dalagatan 100
STOCKHOLM

October 7th: Örebro
Registration: http://www.swenug.se/events/oerebro-silverlight-4-tour-de
Address:
Cityconferencecenter
Klostergatan 23
Örebro

October 8th: Göteborg
Registration: http://www.swenug.se/events/gbg-silverlight-4-tour-de
Address:
Sigma
Lindholmspiren 9
Göteborg

I hope to meet you there!

  Posted on: Friday, September 24, 2010 9:35:41 AM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     .net | .NET 4 | Efficiency | Silverlight | sl4 | VS2010     September 4, 2010    

In April, I was in the UK for speaking at the VBUG conference and I was impressed by a demo given by Josh Twist. He built using MEF and WPF a “marketplace” application. The goal of the application was mainly showing the dynamic capabilities of adding new functionality to an application through MEF (or in full, the Managed Extensibility Framework for Silverlight 4).

For a presentation I’m giving shortly, I rebuilt something similar but in Silverlight: the MEF Marketplace in Silverlight. The setup is the following: a user gets an overview of apps he purchased in the market place and can run these on demand. The market place app will download the applications available to the user after the application has started, so this app mainly is a hosting shell for the other ‘purchased” applications to run in. Of course, the sample is a demo and can be extended quite a lot. For example, in the current implementation, I hard-coded the list of purchased apps and there’s no option to buy new ones. Also, it could be extended so that when new apps are purchased, a duplex service notifies the client of this and MEF downloads the new app in the background.

But, instead of talking of what could be added, let’s take a look at what I currently built already! Here’s a screenshot of the application showing the "purchased” applications.

SNAGHTMLaf6bd

And here’s one of the apps (the Flickr Image search) running inside the "market place shell”.

SNAGHTMLb8796

Time for some code. Let’s begin with the market place itself.

I defined a contract interface for all applications that can be loaded in the market place, IMarketPlaceApplication.

public interface IMarketPlaceApplication
{
    string ApplicationName { get; }
    FrameworkElement MarketPlaceIcon { get; }
    FrameworkElement MainView { get; }
}
This interface defines that all my apps will (of course) have a name, a default view which will load as the landing screen when the app is loaded (MainView.xaml) and an icon to show in the list (MarketPlaceIcon.xaml). As these 2 latest ones are XAML files, you can put in whatever you like.

A very easy application that will be possible to load from MEF is the HelloWorldApplication. The project structure of this app is as follows:

image

As you can see, there’s a class called HelloWorldApplication, which implements the IMarketPlaceApplication and 2 xaml files. The HelloWorldApplication code is shown below:

[Export(typeof(IMarketPlaceApplication))]
public class HelloWorldApplication: IMarketPlaceApplication
{
 
    #region IMarketPlaceApplication Members
 
    public string ApplicationName
    {
        get { return "Hello MEF world"; }
    }
 
    [Import(typeof(Icon))]
    public FrameworkElement MarketPlaceIcon
    {
        get;
        set;
    }
 
    [Import(typeof(HelloWorldView))]
    public FrameworkElement MainView
    {
        get;
        set;
    }
 
    #endregion
}

This is our first encounter with MEF. The first line uses the Export attribute. This class is saying that it is available for someone to use, when someone requests an instance of IMarketPlaceApplication. A bit further, we are using the Import attribute on both the MarketPlaceIcon and the MainView. Here we are saying: MEF, search us a class that’s exporting itself as type Icon and HelloWorldView respectively.

These 2 latter instances will be inserted by MEF upon executing the application, that is, if MEF finds the corresponding export. These exports can be found in the 2 XAML files (in the code-behind). The HelloWorldView.xaml.cs code is shown next. Note the Export attribute: we’re telling to MEF that this type can be used where an Import is requested of the HelloWorldView type.

[Export]
public partial class HelloWorldView : UserControl
{
    
    public HelloWorldView()
    {
        InitializeComponent();
    }
}

The Icon.xaml.cs is pretty similar code-behind-wise (I think I invented that term here): here alse we are adding an Export attribute.

[Export]
public partial class Icon : UserControl
{
    public Icon()
    {
        InitializeComponent();
    }
}

The HelloWorldApplication is at this point a stand-alone application (it compiles to its own XAP file), but we’ll now build the Market Place shell that will host this app. The code download at the end of the article contains several sample applications (a Flickr app and a Facebook app).

Similar to a real market place application, our implementation will get a list of apps you purchased previously. Only these are available to you and will be shown. To get this list, I wrote a basic Silverlight-enabled WCF service that fetches this list of available applications. This service is hosted in this case in the hosting website. The code below shows this service, which in this case returns a hard-coded list of apps (note that I have some more apps already added here).

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = 
    AspNetCompatibilityRequirementsMode.Allowed)]
public class MarketPlaceService
{
    [OperationContract]
    public List<MefApplication> GetAvailableApplicationsForUser()
    {
        return new List<MefApplication>()
        {
            new MefApplication(){ApplicationName="Flickr Image Search", 
                XapFileName="FlickImageSearch.xap"}, 
            new MefApplication(){ApplicationName="Hello World", 
                XapFileName="HelloWorldApplication.xap"},
            new MefApplication(){ApplicationName="MEFacebook", 
                XapFileName="FacebookApplication.xap"}
        };
    }
 
    // Add more operations here and mark them with [OperationContract]
}
 
[DataContract]
public class MefApplication
{
    [DataMember]
    public string ApplicationName { get; set; }
 
    [DataMember]
    public string XapFileName { get; set; }
}

The service uses the MefApplication class as a helper class: it contains the name of the application and more importantly, the name of the XAP file (this could easily be replaced with a Uri to the XAP file).

In the MefMarketPlace, the Silverlight Market Place application, we can create a web reference to this service. In the App.xaml.cs, I add a call to a new method, DownloadMyApplicationList():

private void Application_Startup(object sender, StartupEventArgs e)
{
    DownloadMyApplicationsList();
    this.RootVisual = new MainPage();
}

This new method makes the service call to get a list of available XAPs that I can use (apps that I purchased).

void DownloadMyApplicationsList()
{
    AggregateCatalog = new AggregateCatalog();
 
    container = new CompositionContainer(this.AggregateCatalog);
    CompositionHost.Initialize(container);
 
    MarketPlaceService.MarketPlaceServiceClient client = 
        new MarketPlaceService.MarketPlaceServiceClient();
    client.GetAvailableApplicationsForUserCompleted += 
        new EventHandler<MarketPlaceService.GetAvailableApplicationsForUserCompletedEventArgs>
            (client_GetAvailableApplicationsForUserCompleted);
    client.GetAvailableApplicationsForUserAsync();
}
 
void client_GetAvailableApplicationsForUserCompleted(object sender, 
    MarketPlaceService.GetAvailableApplicationsForUserCompletedEventArgs e)
{
    if (e.Error == null)
    {
        AvailableApplicationsForUser = e.Result;
        InitializeCatalog();
    }
}

In the callback method of the service, I call InitializeCatalog(). MEF has the concept of Catalogs: a Catalog can be used to tell MEF where it has to look for Parts. Several types of catalogs exist in MEF for Silverlight: the TypeCatalog, the AssemblyCatalog, the DeploymentCatalog and the AggregateCatalog. A TypeCatalog basically allows us to register a specific type with MEF: if I want MEF to know about a certain Export, I can register it in a TypeCatalog. An AssemblyCatalog tells MEF to look for parts in a specific assembly. The DeploymentCatalog allows us to specify a XAP file and MEF will look in the assemblies therein for parts. It also allows us to asynchronously download a XAP file. An AggregateCatalog can contain any number of other catalogs and more catalogs can be added at any time.

By default, if we don’t specify a Catalog for our application, MEF looks at the current XAP file and for each assembly it finds, it creates an AssemblyCatalog. It then combines these with an AggregateCatalog. That means that we can omit creating a catalog in our application: in this case, MEF will create a default one for us, with something similar to this code:

void InitializeCatalog()
{
    AggregateCatalog catalog = new AggregateCatalog();
 
    foreach (var deployedPart in Deployment.Current.Parts)
    {
        StreamResourceInfo resourceInfo = 
            Application.GetResourceStream(new Uri(deployedPart.Source, UriKind.Relative));
 
        Assembly assembly = deployedPart.Load(resourceInfo.Stream);
        catalog.Catalogs.Add(new AssemblyCatalog(assembly));
    }
 
    CompositionHost.Initialize(catalog);
}

Back to our application. If we look at the available catalogs in MEF, we can see that the DeploymentCatalog is a good candidate for what we need: we can use it to download a XAP file (the application that we want to load). After that, we can add each DeploymentCatalog to an AggregateCatalog. MEF will then make these available in our application and we can run the downloaded applications.

In code, this gives the following:

private CompositionContainer container;
void InitializeCatalog()
{
 
    foreach (var item in AvailableApplicationsForUser)
    {
        DeploymentCatalog deploymentCatalog = 
            new DeploymentCatalog(item.XapFileName);
        this.AggregateCatalog.Catalogs.Add(deploymentCatalog);
 
        deploymentCatalog.DownloadCompleted += (s, e) =>
        {
            //extend to give meaningful error handling
            if (e.Error != null)
                MessageBox.Show(e.Error.Message);
        };
 
        deploymentCatalog.DownloadAsync();
    }
 
    container.ComposeParts(this);
}

You can see that I use a CompositionContainer here. The container is well, like the word says it, a container where MEF puts all the parts, shakes it up and creates/composes parts.

We now have the code that runs when we start the application: it gets a list of all the applications we can use over the service and then it downloads the XAP files of these apps asynchronously. Each XAP file is downloaded using a DeploymentCatalog and these are added to an AggregateCatalog. This now makes our downloaded applications available to run.

Let’s now take a look at the UI where we’ll run the apps from. The following screenshot shows the UI:

image

The “Load my apps'” button on the top right will execute a command on the viewmodel that will load all available applications in the ListBox on the left.

image

When clicking on the “Load app” button, the selected application (here the Flickr app) is loaded:

image

Clicking the “Home” button unloads the app and returns us to the list screen.

The complete XAML listing can be found in the code download. The most important part is shown below. Note that there’s a ContentPresenter used here and it’s bound to the MainView property of the SelectedApplication. The latter is a property exposed on the viewmodel (see further). If no view/app is selected, this ContentPresenter won’t be visible and we’ll see the default UI again.

<Grid x:Name="LayoutRoot" Background="Black">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="60"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid>
        ...
    </Grid>
 
    <ContentPresenter Content="{Binding SelectedApplication.MainView}">
    </ContentPresenter>
    <Button Grid.Row="1" Content="Home" Margin="10" Background="#FFABE3FF" 
            Command="{Binding HomeCommand}" BorderBrush="#FF00AAFF" 
            Style="{StaticResource ButtonStyle1}" 
            Width="130" Height="40" HorizontalAlignment="Center" 
            VerticalAlignment="Center"></Button>
</Grid>

Time to look at the viewmodel now. Probably the most important part here is the ObservableCollection<IMarketPlaceApplication>:

[ImportMany(AllowRecomposition=true)]
public ObservableCollection<IMarketPlaceApplication> Applications
{
    get
    {
        return _applications;
    }
}

The ListBox in the UI is bound to this collection and since it’s an ObservableCollection, the UI will reflect changes to this collection. That’s important here, since the list of available apps won’t be known after the shell contacted the service. Note that the collection property is attributed with the ImportMany attribute. This is a sign for MEF that more than one part that is exposing itself with the same Export attribute (same type) is allowed. By default, this isn’t allowed since MEF wouldn’t know which one to use. Here, we want the ImportMany since we know that more than one app will be available and they all need to be exported as an IMarketPlaceApplication. Another important thing to note here is the AllowRecomposition option we used here. AllowRecomposition tells MEF that if during the run of the app more Exports become available for this Import, it’s OK to add them, in other words, to rebuild the composition.

The ContentPresenter in the UI bound to SelectedApplication.MainView. The SelectedApplication property is shown next.

private IMarketPlaceApplication _selectedApplication;
 
public IMarketPlaceApplication SelectedApplication 
{
    get
    {
        return _selectedApplication;
    }
    set
    {
        _selectedApplication = value;
        NotifyPropertyChanged("SelectedApplication");
    }
}

NotifyPropertyChanged is a simple method that raises the PropertyChanged event of the INotifyPropertyChanged interface.

private void NotifyPropertyChanged(string p)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(p));
    }
}

The “Load apps” button in the UI is bound to the LoadAppsCommand. I use the MVVM Light RelayCommand here. In the execute code of the ICommand, I ask MEF to satisfy the Imports of the current class (the viewmodel). This basically tells MEF to look at the catalogs and bring all the Export(typeof(IMarketPlaceApplication)) into the ImportMany.

public RelayCommand LoadAppsCommand
{
    get
    {
        if (_loadAppsCommand == null)
        {
            _loadAppsCommand = new RelayCommand(
                    () =>
                    {
                        CompositionInitializer.SatisfyImports(this);
                        loaded = true;
                    },
                    () =>
                    {
                        if (loaded)
                            return false;
                        return true;
                    }
                );
        }
        return _loadAppsCommand;
    }
}

The LoadSelectedApplicationCommand and the HomeCommand respectively set the SelectedApplication property to the selected application in the list or null.

public RelayCommand<IMarketPlaceApplication> LoadSelectedAppCommand
{
    get
    {
        if (_loadSelectedAppCommand == null)
        {
            _loadSelectedAppCommand = new RelayCommand<IMarketPlaceApplication>(
                    (a) => 
                    { 
                        SelectedApplication = a; 
                    }
                );
        }
        return _loadSelectedAppCommand;
    }
}
 
 
public RelayCommand HomeCommand
{
    get
    {
        if (_homeCommand == null)
        {
            _homeCommand = new RelayCommand(
                    () =>
                    {
                        SelectedApplication = null;
                    }
                );
        }
        return _homeCommand;
    }
}

With that, we have successfully implemented the MEF Marketplace. As said in the very beginning, this can be extended quite a lot. Add a duplex service and a buying system that pushes a message to the client and trigger the client to download the linked XAP file is a nice way to start. The complete file can be downloaded below.

Enjoy!

Code download: MefMarketPlace.zip (868.99 KB)

  Posted on: Saturday, September 04, 2010 11:25:11 PM (Romance Daylight Time, UTC+02:00)   |   Comments [2]
         
Gill Cleeren     Book | Efficiency | Silverlight | sl4     September 3, 2010    

I was looking at Amazon today and noticed that there were now already 12 reviews on our (Kevin and myself) book, giving the book a whopping 5 star rating, which is of course great!

9843_Mockupcover

Here are some of the excerpts:

Ideal for those who prefer a tutorial-oriented writing style, August 30, 2010 5.0 out of 5 stars
HOW THIS COOKBOOK WORKED FOR ME: In contrast, this book ("Microsoft Silverlight 4 Data and Services Cookbook" from PACKT) certainly proved valuable to me by appealing to my learning style, and delivering what was advertised on the cover. I was able to learn a reasonable amount of SL4 specifically for handling business data, using "Microsoft Silverlight 4 Data and Services Cookbook". The format and approach is ideal for those among us who prefer to "cut to the chase" instead of wading through lengthy tirades. The examples build on one another which served to reinforce key concepts through out the book-- money well spent from my perspective.

Great Book for Silverlight App Development, June 22, 2010 5.0 out of 5 stars
*Getting ready
*How to do it...
*How it works...
*There's more...
*See also
The ample pictures of both the Visual Studio 2010 GUI and running Silverlight applications augment the many code samples. The section that I have appreciated the most has been the chapter on "Talking to WCF RIA Services" as I am working on developing a better understanding of it.
Now that the summer is here, it's a great time to pick up a book or two to read when you're away from your computer. If you are building or want to build applications with Silverlight, I highly recommend this book and suggest that you get a copy for your summer reading.

Best book for Developers., July 18, 2010 5.0 out of 5 stars
Best book for beginner / intermediate developers who have prior knowledge about basics of Silverlight.

Best Silverlight 4 Book To Date, June 19, 2010 5.0 out of 5 stars
I have read through every well-known Silverlight 4 book on the market. I have even read part of Microsoft Step by Step Silverlight 4 (released yesterday 2010-06-18 on Safari and via ebook) - In my humble opinion, this is the best Silverlight 4 book on the market to date. Most of what I have read from the other Silverlight books is covered in Ian Griffith's Silverlight 4 labs up on the Microsoft Silverlight 4 page. If you want a fast track to learn Silverlight 4 and are already familiar with C# .NET, I would recommend picking up a top rated Silverlight 3 book (I personally like books from the Apress series - "Pro Silverlight 3" and the Silverlight 3 Business Intelligence one (forget the exact title) - then the labs on the official Silverlight 4 website and this book.

life savor, August 25, 2010 5.0 out of 5 stars
I had to write a web-application to demo the WCF Data Service I was writing on a very short time budget. This book was a life savor; it had all the answers I needed for consuming the service and displaying in the datagrid. For server side programming, both Effective REST Services and Essential WCF are great.

The best silverlight book i've seen..., 24 Aug 20105.0 out of 5 stars
This is an excellent book, packed with step by step exercises so you learn by doing rather than just having reading a book as thick as a house brick. Personally I would buy this book to learn Silverlight from scratch, while its true you wont learn a great deal about the controls but you WILL learn the most important aspects which are accessing and displaying data.
I've been a software developer for 6 years after University and bought so many IT books, so far, this has been the best and most readable. I enjoyed reading and practicing the examples in it unlike so many 20 inch thick programming beasts that you dread opening because they just send you to sleep!
Dont hesitate, just buy it.
My only gripe about this book is that when I brought it I thought it was a tad expensive at £35... But, worth it though.

Concise and relevant, 11 Aug 2010 5.0 out of 5 stars
This book covers the essentials of Silverlight and WPF with practical examples that you are going to follow when building your real world applications. It explains WPF binding and DataTemplates well, and what interfaces your business layer objects need to implement to notify when changes occur.
The recipies on WCF communication (sockets, WCF, net.tcp) are great and give examples of when you would best use them, and cover the config file changes needed too.
A refreshingly slim book too - lets face it, who wants a 1000+ page book covering everything and the kitchen sink. You want a straight to the point book that covers the essentials you would use at work and touches all the major areas. Highly recommended.

 

If you want to read more reviews or order my Silverlight 4 Data and services cookbook, head to Amazon.com or Amazon.co.uk or alternatively you can order via the Packt website as well!

  Posted on: Friday, September 03, 2010 10:09:44 AM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     .NET 4 | Book | Efficiency | Silverlight | sl4     May 22, 2010    

With my book I wrote together with Kevin Dockx, Microsoft Silverlight 4 Data and Services Cookbook available for a couple of weeks now, I decided to do a small search on reviews. I’ll be honest, I took all I could find right now.

9843_Mockupcover

Here’s the ones I found:

Richard Costall:

“Microsoft Silverlight 4 Data and Services Cookbook is a great publication, and worthy of a place any Silverlight developers bookshelf. The formula of ‘recipes’ works well, with well explained, yet simple examples covering almost everything you’d ask when starting out building business applications in Silverlight. It highlights Silverlight 2 and Silverlight 3 functionality differences, yet is right up to date on Silverlight 4.”

Complete review at: http://www.nxtgenug.net/Article.aspx?ArticleID=368

Vikram Pendse writes:

“My Review Comments : * * * * * (5 Stars)..Simple Amazing book !..Go and Grab your Copy Today !!! :)

Impressed with this Book?..want to have a look at? Ok ! What you see is what you get ! kidding..You can download a sample chapter right away !”

Complete review at http://pendsevikram.blogspot.com/2010/05/microsoft-silverlight-4-data-and.html

Damir Tomicic writes:

“Das Buch ist sehr praktisch geschrieben. Der Leser merkt sofort, dass Gill und Kevin die Ansätze selbst ausprobiert und für die Leser optimiert haben. Die gewählte Sprache ist einfach, die Beispiele auch für Anfänger geeignet. Ein guter Einstieg in das Thema.”

Complete review at: http://tomicic.de/2010/05/05/MicrosoftSilverlight4DataAndServicesCookbookGillcleeren.aspx

Review on Amazon.com

“Good Introduction to the Datagrid, Dataform, and different Services (4/5)”


Complete review at http://www.amazon.com/Microsoft-Silverlight-Data-Services-Cookbook/product-reviews/1847199844/ref=dp_db_cm_cr_acr_txt?ie=UTF8&showViewpoints=1

Interested in my book as well? It is available from Packt Publishing, Amazon.com, Amazon UK and many other retailers as well! I hope you enjoy it!

  Posted on: Saturday, May 22, 2010 10:06:33 PM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     Efficiency | Silverlight | sl4     April 26, 2010    

Earlier today, I got confirmation that my first book I wrote (together with Kevin Dockx) has been published and can now be ordered, both in e-book and hard copy. This is the new cover. The book also marks the launch of the new brand of Packt, namely Packt Enterprise.

9843_Mockupcover

The e-book version is available from the publisher’s website: https://www.packtpub.com/microsoft-silverlight-4-data-and-services-cookbook/book . On this site, you can also get a discount on the printed version.

You can also buy the book from Amazon of course (which at this moment still lists it as pre-order though). If you shop at Amazon.com, you can get your copy here: http://www.amazon.com/Microsoft-Silverlight-Data-Services-Cookbook/dp/1847199844. If you rather order at Amazon UK, you can order here: http://www.amazon.co.uk/Microsoft-Silverlight-Data-Services-Cookbook/dp/1847199844/ref=sr_1_1?ie=UTF8&s=books&qid=1272289229&sr=8-1.

If you want to get a more in-depth look at what the book has to offer, take a look here: https://www.packtpub.com/microsoft-silverlight-4-data-and-services-cookbook/book#in_detail .

What the book is about:

Silverlight 3 made a big step into Line-Of-Business applications and Silverlight 4 builds further on this. This book is not a general Silverlight 4 overview book; it is uniquely aimed at developers who want to build data-driven applications using Silverlight. It focuses on showing . NET developers how to interact with and handle multiple sources of data in Silverlight business applications and how to solve particular data problems, following a practical hands-on approach, using real-world recipes in a practical cookbook format. The book is aimed at Silverlight 4, however most of the covered features work both in Silverlight 3 and 4.

By following the practical recipes in this book, you will learn the concepts needed to create data-rich business applications—from the basic creation of a Silverlight application, to displaying data using data binding and upgrading your existing applications to use Silverlight.

Who this book is written for:

If you are a .NET developer who wants to build professional data-driven applications with Silverlight, then this book is for you. Basic Silverlight experience and familiarity with accessing data using ADO.NET in regular .NET applications is required.

What you will learn from this book:

  • Display and validate data efficiently in Silverlight business applications using data binding
  • Use the full power of the important data controls in Silverlight such as the DataGrid and the DataForm
  • Discover how your Silverlight business applications can quickly access data residing in a database or even Windows Azure by calling web services using XML, RSS, JSON and more
  • Exchange information between Silverlight clients and WCF or ASMX services in your Silverlight business applications
  • Add functionality to your Silverlight business applications by harnessing REST and WCF Data Services
  • Communicate with well-known REST APIs such as Flickr and Twitter from Silverlight
  • Simplify your data-driven business application development with WCF RIA Services

You can also read some sample recipes on the Packt site here: https://www.packtpub.com/article/inserting-updating-deleting-sorting-grouping-displaying-data-grid-silverlight .

I do hope you’ll like the book. If you have any questions on the book, don’t hesitate to mail me at silverlight@snowball.be .

  Posted on: Monday, April 26, 2010 4:32:01 PM (Romance Daylight Time, UTC+02:00)   |   Comments [3]
         
Gill Cleeren     .net | .NET 4 | C# | Silverlight | sl4 | VS2010     April 12, 2010    

After beta’s and one RC release, starting today, we can get our hands on Visual Studio 2010 RTM. Just hours ago, Microsoft held a keynote on the release of their flagship IDE, Visual Studio 2010. This release coincides with the release of .NET 4.0 and of course Silverlight 4, which has its official launch event tomorrow. This marks probably the largest release ever for developers from Microsoft.

 image

I need it badly

Visual Studio 2010 is like honey, developers swarm to it. It’s understandable that you want to get your hands on the bits. Where can you get them?
If you’re an MSDN subscriber, you’re in luck, as you can get all the bits from the MSDN subscription site. (http://msdn.microsoft.com/subscriptions)
If you are not, you have the following options:

image

 

Why you need it

If I wanted to make a list of reasons why you should be upgrading to Visual Studio 2010, I would be up all night I think. Since it’s quite late already, I’m going to make an all-but-complete list with my top features that make Visual Studio 2010 an not-to-miss upgrade. (For the complete list – you’re warned, it’s very complete – take a look here: http://msdn.microsoft.com/en-us/library/bb386063(VS.100).aspx)

The IDE looks really stylish!

Upon opening Visual Studio 2010 for the first time, you’ll immediately notice that something happened… Something big. No longer the traditional grey interface, but an exciting new look for the place you spend all your development hours in. Built entirely in WPF, the new shell offers plenty of extension points so you can make it feel even more like home.

image

New IDE features

I personally like the Navigate To function a lot (I blogged about it yesterday here: Visual Studio 2010 Tip- Navigate to functionality). Another one I like is the zoom in/out we can now do in the code editor. This is a real life-saver when doing demos on stage or when showing someone some code. Simply keep CTRL key pressed and rotate that mouse wheel of yours. For people who work on multiple monitors, Visual Studio now supports this much better!

Some other nice features:

  • Improved IntelliSense
  • Highlight references
  • Stub generation

New framework and languages

Visual Studio 2010 comes packed with new releases.

  • Silverlight 4 :) More on this at the launch event tomorrow!
  • C# 4.0 adds interesting new features to the language (more here). Also VB.net developers aren’t left outside in the cold, their favorite language gets an upgrade as well to Visual Basic 2010.
  • ASP.NET 4.0 as well as MVC 2 are born! If you want to get an overview of what’s new, download my talk of DevDays 2010 here. Most striking new features in WebForms 4 are client IDs, control over ViewState and more control over the HTML that’s being rendered.
  • Entity Framework makes a jump and goes straight to v4.
  • WCF and WF both get an upgrade to v4 as well.
  • TFS installation gets really simple using TFS Basic.
  • F# is now available for the functional programming needs.
  • SharePoint templates!

I want more

Not enough reading material for your brain? A free ebook is made available “Moving to Visual Studio 2010” here.

Warnings here!

Something to watch out for: currently, the Windows Phone 7 tools do not work with the RTM version of 2010. Read more on this here: http://forums.silverlight.net/forums/t/175181.aspx 

image

  Posted on: Monday, April 12, 2010 11:54:13 PM (Romance Daylight Time, UTC+02:00)   |   Comments [1]
         
Gill Cleeren     .NET 4 | Events | Silverlight | sl4 | Slide decks     April 4, 2010    

Overlapping with the Dutch DevDays event this year, I was of course present at TechDays 2010 Belgium as well. TechDays really became a big event with lots of attendees, speakers and sponsors. Never before had the line-up of speakers been so impressive, with names such as Anders Hejlsberg, Scott Hanselman, Charley Kindel… The feedback that I’ve heard was very positive, with the general comment being that the session content was good, deep dive and well brought by the speakers.

I got 2 session slots:

  • Silverlight 4 Tour de Force with a little WPF 4 sauce on top (together with Katrien De Graeve)
  • Building Data-Driven applications FAST with RIA services and Silverlight

As promised during the talks, I have uploaded all slide decks and demos for both sessions below. You can download them and use them as you like.

  • Silverlight 4 Tour de Force with a little WPF 4 sauce on top
  • Building Data-Driven applications FAST with RIA services and Silverlight

I took some pictures during the event as well. Below I posted some, the entire set can be seen here.

IMG_0079 IMG_0106 IMG_0083

IMG_0095 IMG_0104 IMG_0092

  Posted on: Sunday, April 04, 2010 5:06:40 PM (Romance Daylight Time, UTC+02:00)   |   Comments [0]
         
Gill Cleeren     Silverlight | sl4     March 8, 2010    

As many of you may already know, I’m working on a book titled Silverlight 4 Data and Services Cookbook. Writing my first book (together with fellow Silverlight addict Kevin Dockx) has taken a lot of my time, I haven’t been able to blog as much as I used to. My sincere apologies for that :)

The good news is that the book is almost done, we’re in the last straight line to the publication stage! Even more good news is that the book is already available for pre-order at the publisher’s site: http://www.packtpub.com/microsoft-silverlight-4-data-and-services-cookbook/book .

1847199844

The contents of the books is the following:

Over 85 practical recipes for creating rich, data-driven business applications in Silverlight

  • Design and develop rich data-driven business applications in Silverlight
  • Rapidly interact with and handle multiple sources of data and services within Silverlight business applications
  • Understand sophisticated data access techniques in your Silverlight business applications by binding data to Silverlight controls, validating data in Silverlight, getting data from services into Silverlight applications and much more!
  • Packed with practical, hands-on cookbook recipes, illustrating the techniques to solve particular data problems effectively within your Silverlight business applications

In detail:

Microsoft Silverlight is a programmable web browser plugin that enables features including animation, vector graphics, and audio-video playback – features that characterize Rich Internet Applications. However, Silverlight is a great (and growing) Line-Of-Business platform and is increasingly being used to build data-driven business applications. Silverlight Data Services enable efficient access to your data, allowing you to draw on multiple sources of data and solve particular data problems. There is very little existing material that demonstrates how to build data-driven solutions with the platform. Silverlight 3 made a big step into Line-Of-Business data services and Silverlight 4 builds further upon this. This book will enable .NET developers to get their finger on the pulse of data-driven business applications in Silverlight.

This book is not a general Silverlight 3/4 overview book; it is uniquely aimed at developers who want to build data-driven applications. It focuses on showing .NET developers how to interact with, and handle multiple sources of data in Silverlight business applications, and how to solve particular data problems following a practical hands-on approach, using real-world recipes. It is a practical cookbook that teaches you how to build data-rich business applications with Silverlight that draw on multiple sources of data. Most of the covered features work both in Silverlight 3 and 4. However, we cover some that are specific for Silverlight 4, which will therefore not work with Silverlight 3. Where this is the case, it is clearly indicated.

Packed with reusable, real-world recipes, the book begins by introducing you to general principles when programming Silverlight. It then dives deep into the world of data services, covering all the options available to access data and communicate with services to get the most out of data in your Silverlight business applications, whilst at the same time providing a rich user experience. Chapters cover data binding, data controls, the concepts of talking to services, communicating with WCF, ASMX and REST services, and much more.

By following the practical recipes in this book, which are of varying difficulty levels, you will learn the concepts needed to create data-rich business applications—from the creation of a Silverlight application, to displaying data in the Silverlight application and upgrading your existing applications to use Silverlight. Each recipe covers a data services topic, going from the description of the problem, through a conceptual solution to a solution containing sample code.

I’m really really excited about the upcoming release, I hope you enjoy reading it as much as I did writing it! As you can see, the book takes a very practical approach to working with Silverlight in enterprise environments using a recipe-approach. The scenarios for these recipes are things me an you often encounter and this book should give you the solution for them. The book is aimed at Silverlight 4 development, although most recipes will work in Silverlight 3 as well.

I hope in the coming weeks/months to be able to give away a few copies of the book from here.

  Posted on: Monday, March 08, 2010 11:31:07 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 23, 2009    

Yes, I made it :) Welcome to this last post in my Silverlight Advent Calendar! From December 1st until today, December 24th, I have created each day, a Silverlight article. When I first thought about it, I feared there would be at least one day I would not be able to create my post. Well, this didn’t happen, and this means that after 24 articles, we have finally arrived at Christmas Eve. I really hope you enjoyed these posts and I’ll sure be doing something similar in the future!

On a “real” advent calendar, on December 24th, the final day of the calendar, you get a special surprise: a bigger image, a bigger gift or a larger chunk of chocolate than on other days. Well, I thought this needed to be the case in my advent calendar as well, so I decided to end my series with a special post. It gives a preview of something that can in much more detail be found in my upcoming book AND it brings some more Christmas spirit on this day: a Flickr Christmas image browser. All free as my gift to you!

Below is the interface of the application.

image

We’re in luck when working with Flickr: it exposes a cross-domain file so we can access their API services from a client Silverlight application, even without running with elevated permissions! Therefore, we do not need to create a service layer that sits in between our application and Flickr’s services.

When clicking on the Get Pictures button, we load thumbnails into a templated StackPanel. When clicking on any of these thumbnails, the large image is loaded. To store the information needed for a thumbnail, I created a class called SmallFlickrImage.

public class SmallFlickrImage
{
  public string ImageId { get; set; }
  public string FarmId { get; set; }
  public string ServerId { get; set; }
  public string Secret { get; set; }
 
  public string ImageUrl
  {
    get
    {
      return string.Format(
        "http://farm{0}.static.flickr.com/{1}/{2}_{3}_m.jpg", 
        FarmId, 
        ServerId, 
        ImageId, 
        Secret
        );
    }
  }
}

In the click event, we perform a service call to Flickr. To call Flickr’s API, you’ll need an API key which can be obtained for free at http://www.flickr.com/services/api/. Once obtained, you need to embed this key in each request your application will perform with Flickr. Also on this site, you’ll find a complete overview of all available methods. Here, I’m using the flickr.photos.search method, which accepts a search string and returns me an XML response, containing all the information I need to display images in my client side application.

Working with Flickr is a typical example of a REST service. When working with these services from Silverlight, we actually need to do 3 steps:

  • Create a URL
  • Send a request to this URL
  • Accept the response, mostly in XML, sometimes in JSON

The URL is constructed as follows (as directed by Flickr):

string searchUrl = 
  "http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key={0}
   &text=christmas tree snow";

To send a request to this URL, we can use either the WebClient, or the HttpWebRequest. WebClient is sufficient (there are cases where this is not the case, I spent many pages to this topic in my book ;) ). Working in Silverlight with WebClient is identical to working with this class in the full .NET framework. One thing though: just like any interaction with a service, the service call is to be done asynchronously. The code below sends a request to Flickr:

private void GetPicturesButton_Click(object sender, RoutedEventArgs e)
{
    WebClient client = new WebClient();
    client.DownloadStringCompleted += 
      new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    client.DownloadStringAsync(new Uri(string.Format(searchUrl, api_key)));
}

In the callback, which is invoked automatically when the service returns, using some very simple LINQ-To-XML, we can parse the results. The returned XML is always of the same format and can be seen as the contract between Flickr and my application. Because we cannot set the Source property of an Image control directly, we need to go around using a BitmapImage.

protected void client_DownloadStringCompleted(object sender, 
  DownloadStringCompletedEventArgs e)
{
  XDocument xml = XDocument.Parse(e.Result);
 
  var photos = from results in xml.Descendants("photo")
               select new SmallFlickrImage
               {
                 ImageId = results.Attribute("id").Value.ToString(),
                 FarmId = results.Attribute("farm").Value.ToString(),
                 ServerId = results.Attribute("server").Value.ToString(),
                 Secret = results.Attribute("secret").Value.ToString()
               };
 
  foreach (var photo in photos)
  {
    Image image = new Image();
 
    BitmapImage bitmapImage = new BitmapImage(new Uri(photo.ImageUrl, UriKind.Absolute));
    image.Source = bitmapImage;
    image.Width = 160;
    image.Height = 160;
    image.Stretch = Stretch.Uniform;
    image.Tag = photo;
    image.Margin = new Thickness(3);
    image.HorizontalAlignment = HorizontalAlignment.Center;
    image.MouseLeftButtonDown += new MouseButtonEventHandler(img_MouseLeftButtonDown);
    PicListBox.Items.Add(image);
  }
}

At this point, the ListBox is filled. This ListBox is templated; the code for this can be seen in the sample code download.

When clicking (we attached a MouseLeftButtonDown event on each dynamically added image) on an image, we’ll load the "full” image into an Image control. This requires some code, mostly concerning which type of URL is used by Flickr for the image.

void img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  Image img = sender as Image;
  SmallFlickrImage smallFlickrImage = img.Tag as SmallFlickrImage;
  if (smallFlickrImage != null)
  {
    WebClient detailClient = new WebClient();
    detailClient.DownloadStringCompleted += 
      new DownloadStringCompletedEventHandler(detailClient_DownloadStringCompleted);
    detailClient.DownloadStringAsync(
      new Uri(string.Format(detailUrl, api_key, smallFlickrImage.ImageId)));
  }
}
 
void detailClient_DownloadStringCompleted(object sender, 
  DownloadStringCompletedEventArgs e)
{
  XDocument xmlDocument = XDocument.Parse(e.Result);
  XElement photoElement;
  Uri detailImageUrl;
 
  if (xmlDocument.Descendants("photo").Count<XElement>() > 0)
  {
    photoElement = xmlDocument.Descendants("photo").First<XElement>();
 
    string serverId = photoElement.Attribute("server").Value;
    string farmId = photoElement.Attribute("farm").Value;
    string imageId = photoElement.Attribute("id").Value;
    string secret;
    
    if (photoElement.Attribute("originalsecret") != null)
    {
      secret = photoElement.Attribute("originalsecret").Value;
      detailImageUrl = new Uri(string.Format
        ("http://farm{0}.static.flickr.com/{1}/{2}_{3}_o.jpg", 
          farmId, 
          serverId, 
          imageId, 
          secret)
         );
    }
    else
    {
      secret = photoElement.Attribute("secret").Value;
      detailImageUrl = new Uri(string.Format
        ("http://farm{0}.static.flickr.com/{1}/{2}_{3}.jpg", 
          farmId, 
          serverId, 
          imageId, 
          secret)
         );
    }
 
    BitmapImage bitmapImage = new BitmapImage(detailImageUrl);
    DetailImage.Source = bitmapImage;
  }
}

 

With that, the sample is working!

The complete code sample can be downloaded here: SLChristmasFlickr.zip (31.34 KB)

MERRY CHRISTMAS!

  Posted on: Thursday, December 24, 2009 12:50:15 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 20, 2009    

In the before-last post of my Silverlight Advent Calendar, I would like to spend some time with a Silverlight 3 feature that’s most helpful in real world projects: merged resource dictionaries. By most helpful, I mean that in real applications, resource files can become really really big. Files of 1000 lines of pure mark-up are no exception and are really hard to find your way in.

Silverlight 3 added support for merged dictionaries. Basically, using these, we can split resources over several files, dictionaries. Using them though is nothing different than using resources located in App.xaml or Resources of the current page/control.

Let’s take a look at using these merged resource dictionaries. I created some styles to style the ChristmasSong application we have been using a few times already.

 

image

In the beginning of this series, we already looked at implicit styles. For this application, I’m defining a few of these, meaning that this very project will only work for Silverlight 4. Of course, the merged dictionary function works also in Silverlight 3.

To define a resource dictionary, in the project, we need to add a XAML file (either via creating an empty text file and renaming the extension or creating a new user control and deleting the *.cs file). In this file, we can create a ResourceDictionary element. Below is the XAML code for the implicit styles, which I grouped into a file called DefaultStyles.xaml. I created a default style for a Button, TextBlock and TextBox.

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="Button">
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="Background" Value="Red" />
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="FontSize" Value="15" />
        <Setter Property="HorizontalAlignment" Value="Center"></Setter>
        <Setter Property="VerticalAlignment" Value="Center"></Setter>
    </Style>
 
    <Style TargetType="TextBlock">
        <Setter Property="Foreground" Value="Green" />
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="FontSize" Value="15" />
        <Setter Property="HorizontalAlignment" Value="Left"></Setter>
        <Setter Property="VerticalAlignment" Value="Center"></Setter>
        <Setter Property="Margin" Value="2"></Setter>
    </Style>
 
    <Style TargetType="TextBox">
        <Setter Property="Width" Value="150" />
        <Setter Property="FontSize" Value="15" />
        <Setter Property="HorizontalAlignment" Value="Center"></Setter>
        <Setter Property="VerticalAlignment" Value="Center"></Setter>
        <Setter Property="Margin" Value="2"></Setter>
    </Style>
</ResourceDictionary>

Next, I created a second ResourceDictionary which has just one Style, designed for the title, in a file called SpecificStyles.

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="TextBlock" x:Key="TitleStyle">
        <Setter Property="Foreground" Value="Red" />
        <Setter Property="FontStyle" Value="Italic"></Setter>
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="FontSize" Value="28" />
        <Setter Property="HorizontalAlignment" Value="Center"></Setter>
        <Setter Property="VerticalAlignment" Value="Center"></Setter>
    </Style>
</ResourceDictionary>

Now we need to let our application know about these resources. To do so, I have in the App.xaml added the following code. In the MergedDictionaries element, we link the seperate XAML files.

<Application 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  x:Class="SLMergedDictionaries.App"
  >
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary 
          Source="/SLMergedDictionaries;component/DefaultStyles.xaml">
        </ResourceDictionary>
        <ResourceDictionary 
          Source="/SLMergedDictionaries;component/SpecificStyles.xaml">
        </ResourceDictionary>
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

We can now use the styles declared in the dictionaries just like we would do with regular defined styles.

The complete sample can be downloaded here: SLMergedDictionaries.zip (310.39 KB)

  Posted on: Monday, December 21, 2009 12:46:11 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 20, 2009    

Next to the full support of the data binding engine for the IDataErrorInfo interface, Silverlight 4 adds a new interface called INotifyDataErrorInfo, offering more options for particular scenario's. In this post, we’ll look at a small example using this interface.

IDataErrorInfo allows retrieving the error on a per-property basis. It’s not possible however to validate all properties of the entity in one go. This becomes possible with the INotifyDataErrorInfo. Let’s look at the interface first.

public interface INotifyDataErrorInfo
{
    bool HasErrors { get; }
 
    event EventHandler ErrorsChanged;
 
    IEnumerable GetErrors(
                    string propertyName);
}

This interface has some nice advantages. As said, we can check if the entity as a whole is in an invalid state through the HasErrors property. Retrieving the errors using the GetErrors can now retrieve other things than just strings which was all that we could do with the IDataErrorInfo. On top of that, a property can have more than just one validation error at the same time

The ErrorsChanged event can come in handy if there’s a long running process needed to perform validation: assume that for some validation, we need to go to the database over a service. The ErrorsChanged event allows us to notify the UI if the validation errors change. If ValidatesOnNotifyDataErrors is set to true on the UI, Silverlight will listen for the ErrorsChanged event and will display any errors if they are added afterwards.

That’s it for this interface, let’s now look at it in an example. I have changed the example created for the IDataErrorInfo to work with INotifyDataErrorInfo, so the interface has remained the same.

The errors I want to return to my interface are more than just strings. I created a custom error as follows:

public class ChristmasSongError
{
    public ErrorLevel Severity{ get; set; }
    public string ErrorName { get; set; }
    public string ErrorMessage { get; set; }
 
    public override string ToString()
    {
        return ErrorName + ": " + ErrorMessage;
    }
}

The ChristmasSong class now implements the INotifyDataErrorInfo interface. Let’s focus on the Title property. When its value is set, it calls a validation method. In this method, I create an instance of the custom error, specifying all the property values. If there’s an error, here the title being empty, I add it to a Dictionary called errors using the AddError method. If validation is satisfied, it’s removed using the RemoveError method. The errrors Dictionary is used so it is possible for each property to have more than one error: each property has as its value a List.

public class ChristmasSong : INotifyDataErrorInfo
{
    private string title;
    private string performedBy;
    private TimeSpan duration;
    private DateTime published;
 
    private string error;
 
    public Dictionary<string, List> errors = 
      new Dictionary<string,List>();
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(
                    this, new PropertyChangedEventArgs(propertyName));
    }
 
    public string Title
    {
        get
        {
            return title;
        }
        set
        {
            title = 
                    value;
            ValidateTitleProperty();
        }
    }
 
    private void ValidateTitleProperty()
    {
        ChristmasSongError christmasSongError =
new ChristmasSongError() 
        { Severity = ErrorLevel.Error, ErrorName =
"TitleRequired", 
          ErrorMessage = 
                    "Title should not be empty" };
        if (string.IsNullOrEmpty(title))
        {
            AddError(
                    "Title", christmasSongError);
        }
        else
        {
            RemoveError(
                    "Title", "TitleRequired");
        }
    }
 
    public string PerformedBy
    {
        get
        {
            return performedBy;
        }
        set
        {
            performedBy = 
                    value;
            ValidatePerformedByProperty();
        }
    }
 
    private void ValidatePerformedByProperty()
    {
        ChristmasSongError christmasSongError =
new ChristmasSongError() 
        { Severity = ErrorLevel.Error, ErrorName =
"PerformedByRequired", 
          ErrorMessage = 
                    "The artist should not be empty" };
        if (string.IsNullOrEmpty(performedBy))
        {
            AddError(
                    "PerformedBy", christmasSongError);
        }
        else
        {
            RemoveError(
                    "PerformedBy", "PerformedByRequired");
        }
    }
 
    public TimeSpan Duration
    {
        get
        {
            return duration;
        }
        set
        {
            duration = 
                    value;
            ValidateDuration();
        }
    }
 
    private void ValidateDuration()
    {
        ChristmasSongError durationNullError =
new ChristmasSongError() 
        { Severity = ErrorLevel.CriticalError, ErrorName =
"DurationNull", 
          ErrorMessage = 
                    "The duration should not be empty" };
        ChristmasSongError durationTooLongError =
new ChristmasSongError() 
        { Severity = ErrorLevel.Error, ErrorName =
"DurationTooLong", 
          ErrorMessage = 
                    "The duration is too long" };
        
        if (duration == TimeSpan.Zero)
        {
            AddError(
                    "Duration", durationNullError);
        }
        else
        {
            RemoveError(
                    "Duration", "DurationNull");
        }
 
        if (duration.TotalSeconds > 500)
        {
            AddError(
                    "Duration", durationTooLongError);
        }
        else
        {
            RemoveError(
                    "Duration", "DurationTooLong");
        }
    }
 
    public DateTime Published
    {
        get
        {
            return published;
        }
        set
        {
            published = 
                    value;
            VaidatePublished();
        }
    }
 
    private void VaidatePublished()
    {
        ChristmasSongError publishedTooLow =
new ChristmasSongError() 
        { Severity = ErrorLevel.CriticalError, ErrorName =
"PublishedTooLow", 
          ErrorMessage = 
                    "The date is too small" };
        ChristmasSongError publishedTooHigh =
new ChristmasSongError() 
        { Severity = ErrorLevel.CriticalError, ErrorName =
"PublishedTooHigh", 
          ErrorMessage = 
                    "The date is too high" };
 
        if (published < new DateTime(1900, 1, 1))
        {
            AddError(
                    "Published", publishedTooLow);
        }
        else
        {
            RemoveError(
                    "Published", "PublishedTooLow");
        }
 
        if (published > new DateTime( 2010, 1, 1))
        {
            AddError(
                    "Published", publishedTooHigh);
        }
        else
        {
            RemoveError(
                    "Published", "PublishedTooHigh");
        }
    }
 
    private void AddError(string propertyName, ChristmasSongError error)
    {
        
 
        if (!errors.ContainsKey(propertyName))
        {
            errors.Add(propertyName, 
                    new List() { error });
        }
        else// adding the error to the already existing list
        {
            var list = errors[propertyName];
            list.Add(error);
        }
 
        if (ErrorsChanged != null)
            ErrorsChanged(
                    this, new DataErrorsChangedEventArgs(propertyName));
    }
 
    private void RemoveError(string propertyName, string errorName)
    {
        if (errors.ContainsKey(propertyName))
        {
            var christmasSongError = errors[propertyName]
                .Where
(e => e.ErrorName == errorName).FirstOrDefault();
            var list = errors[propertyName];
            list.Remove(christmasSongError);
 
            if (list.Count == 0)//no more errors for this property 
            {
                errors.Remove(propertyName);
            }
 
            if (ErrorsChanged != null)
                ErrorsChanged(
                    this, new DataErrorsChangedEventArgs(propertyName));
        }
    }
 
    public event EventHandler ErrorsChanged;
 
    public System.Collections.IEnumerable GetErrors(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))//retrieve
                        errors for entire entity
        {
            return errors.Values;
        }
        else
        {
            if (errors.ContainsKey(propertyName))
                return errors[propertyName];
            return null;
        }
    }
 
    public bool HasErrors
    {
        get
        {
            if (errors.Count == 0)
                return false;
            return true;
        }
    }
}

With the entity in place, we can look at the UI. The XAML code is similar to the IDataErrorInfo example, although we should now use the ValidatesOnNotifyDataErrors and set it to True. Below is part of the code, for the entire listing, see the download.

<TextBox x:Name="TitleTextBox" Grid.Row="1" Grid.Column="1" Width="200" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="2"

Text="{Binding Path=Title,Mode=TwoWay,ValidatesOnNotifyDataErrors=True,NotifyOnValidationError=True}" />

The complete sample can be downloaded here: SLINotifyDataErrorInfo.zip (602.56 KB)

  Posted on: Monday, December 21, 2009 12:42:27 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 20, 2009    

Services and data access are the focus of the book I’m writing (more very very soon!). Working with services to get data into a Silverlight application is so vital, it should be code that’s known by every Silverlight developer by heart. Working with duplex bindings is somewhat more complicated. However, there are situations in which duplex communication is really necessary. Think of the typical example: a stock application that should send stock updates to the client without the client requesting for an update.

Duplex communications are possible with WCF. They “seem” initiated by the server: the service will send updates without the client requests the service to do so. This way, the client can receive updates whenever new information is available on the server (new stock info that becomes available) and act accordingly. I put seem between quotes. The reason for that is that a duplex binding is in fact still a normal request/receive process. Initially, the client has to do a request to the service and from then on, the service can send its updates to the client.

In the example I have created for this post, I created an application that posts updates about snow throughout Belgium (while writing this article, it has snowed quite a lot in Belgium, so that’s where the inspiration came from and Tienen is where I live :) ). Below is a screenshot.

image

Of course, you’re here to learn something and see some code, right? No problem! Let’s first focus on the service. For the data exchange, I created a small type called SnowUpdate.

public class SnowUpdate
{
    public string Location { get; set; }
    public double centimeter { get; set; }
}

One very important thing that we need to do, is adding a reference to an assembly available in the Silverlight SDK called System.Service.PollingDuplex.dll. By default, it’s installed in C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Server. Add a reference to this assembly. (Note the x86, that’s because I’m running 64bit).

The contract of the service makes it clear that we are working with a duplex service. There are some special things to note in this code. As you can see, two interfaces are defined here. The first one is the regular contract, the second one is what’s called the callback contract and defines the contract for the call to the client.

Also note that both OperationContracts have IsOneWay set to true. For the Connect method, we’re actually saying: a client can call Connect to make itself known to the service but it expects no response, hence the IsOneWay.

[ServiceContract(Namespace = "Silverlight", CallbackContract = typeof(ISnowServiceClient))]
public interface ISnowService
{
    [OperationContract(IsOneWay = true)]
    void Connect();
}
 
[ServiceContract]
public interface ISnowServiceClient
{
    [OperationContract(IsOneWay = true)]
    void SendSnowUpdate(SnowUpdate snowUpdate);
}

In the service implementation, I have created a Timer, which will periodically send a new message to the client. The OperationContext.Current.GetCallbackChannel gives us access to the callback channel which we can use to send messages to the client side. On a tick of the Timer, we’re sending a message.

private ISnowServiceClient client;
private Timer timer;
 
public void Connect()
{
    client = OperationContext.Current.GetCallbackChannel<ISnowServiceClient>();
    timer = new Timer(new TimerCallback(TimerTick), null, 500, 5000);
}
 
void TimerTick(object state)
{
    try
    {
        if (client != null)
        {
            client.SendSnowUpdate(GetLatestUpdate());
        }
    }
    catch (Exception)
    {
 
        client = null;
        timer.Dispose();
    }
}

With that, the service code is done, but it does require some specific configuration code to work. Take a look at the sample for this code. We can now look at the client code. The process to add a service reference is exactly the same, although you’ll notice that the ServiceReferences.clientconfig file remains empty (which it does not when referencing a normal service). Therefore, the code that we need to write is somewhat more complex: we have to create the binding and the address from code and pass this along with the proxy instantiation. Below you can see the client-side code.

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
  EndpointAddress address = new EndpointAddress("http://localhost:59485/SnowService.svc");
 
  CustomBinding binding = new CustomBinding(
    new PollingDuplexBindingElement(),
    new BinaryMessageEncodingBindingElement(),
    new HttpTransportBindingElement());
  
  client = new SLDuplexSnow.SnowService.SnowServiceClient(binding, address);
 
  client.SendSnowUpdateReceived += 
    new EventHandler<SLDuplexSnow.SnowService.SendSnowUpdateReceivedEventArgs>
     (client_SendSnowUpdateReceived);
    client.ConnectAsync();
}
 
void client_SendSnowUpdateReceived(object sender, 
  SLDuplexSnow.SnowService.SendSnowUpdateReceivedEventArgs e)
{
    SnowDetailsGrid.DataContext = e.snowUpdate;
}

Note that we are calling ConnectAsync to let the service know about the client so it can send updates to it BUT we are handing SnowUpdateReceived events.

NOTE: This sample is written for Silverlight 3/VS2008. At this point, I have issues with VS2010 when generating the client proxy with SL4/VS2010 when using a duplex service.

The complete code can be downloaded here: SLDuplex.zip (111.91 KB)

  Posted on: Monday, December 21, 2009 12:38:33 AM (Romance Standard Time, UTC+01:00)   |   Comments [4]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 19, 2009    

In today’s post, we’ll take a look at Silverlight’s Isolated Storage, a feature already available in Silverlight since version 2. With this post, I want to show all there is possible with this handy option.

We all know cookies, small text files that are stored on our machines by sites. Most of the time, the goal of a cookie, is storing informational data for next visits of the user to that particular site. This data can vary from login information to perhaps a background color the user favors. Cookies are limited to containing just plain text as well as in size.

Isolated storage does not differ that much from cookies. It’s basically a file store for Silverlight: Silverlight applications can store in the Isolated Storage files during a session and retrieve them in a later session. Isolated storage is a per-user per-application storage, meaning that when userA works with SilverlightAppA, he’ll have a different isolated storage from userB working with the same application. Isolated storage information is not deleted when you clear your temporary internet files, it can be deleted through the Silverlight configuration, as shown below.

image

We can use isolated storage in a number of ways. Let’s take a look at the sample for this post. Below is a screenshot of the very simple UI I created for this sample. It allows a user to enter a text, representing his preferred background color for the application. We’ll store this value using the IsolatedStorage. Secondly, using another feature called IsolatedStorageSettings, I’m allowing the user to store a second value, which is used for the color of a StackPanel ( the blue bar in the screenshot).

image

First, let’s look at the code for the background color, using the regular IsolatedStorage. Below you can see the code. Working with IsolatedStorage is done using the IsolatedStorageFile class. It defines among others, the GetUserStoreForApplication static method, which returns the data store, for the specific user and the current application. From there on, working with IsolatedStorage is similar to working with the regular file system. Isolated storage is not to be seen as one file, it’s an entire file system, that can contain directories and files. In this code, we are creating using System.IO code a file called color.txt and writing some data to this file.

private void ColorButton_Click(object sender, RoutedEventArgs e)
{
  try
  {
    IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
 
    using (IsolatedStorageFileStream fs = isoStore.CreateFile("color.txt"))
    {
      StreamWriter writer = new StreamWriter(fs);
      writer.Write(ColorTextBox.Text);
      writer.Close();
    }
    ChangeColor(ColorTextBox.Text);
  }
  catch (Exception)
  {
    //handle error here, not for demo
  }
}

On load of the application, we need to check if this file already exists and if yes, read the file and set the background to that specific color. This is shown in the code below.

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
  try
  {
    IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
 
    if (isoStore.FileExists("color.txt"))
    {
      using (IsolatedStorageFileStream fs = isoStore.OpenFile("color.txt", FileMode.Open))
      {
        StreamReader reader = new StreamReader(fs);
        ChangeColor(reader.ReadLine());
        reader.Close();
      }
    }
  }
  catch (Exception)
  {
    //handle error here, not for demo
  }
}

In ASP.NET, we have the Application and Session objects, which provide an easy and quick way to store information between requests. Through a feature of the IsolatedStorage, we can have something quite similar. The IsolatedStorageSettings allow us a key/value lookup to store data. We don’t have to write code to actually store the files, it does that for us. Take a look at the following code. We allow the user to store a second string for the background of the StackPanel.

private void AppColorButton_Click(object sender, RoutedEventArgs e)
{
  IsolatedStorageSettings.ApplicationSettings["AppColor"] = AppColorTextBox.Text;
  ChangeStackPanelColor(AppColorTextBox.Text);
}

Using this approach, we say for the AppColor value, store the contents of the TextBox as value. Behind the scenes, this is persisted, so it can be retrieved after the application has been shutdown (it is thus not stored in application memory). Retrieving the value can be done as follows:

if (IsolatedStorageSettings.ApplicationSettings.Contains("AppColor"))
{
  string appColor = IsolatedStorageSettings.ApplicationSettings["AppColor"].ToString();
  ChangeStackPanelColor(appColor);
}

The complete sample can be downloaded here: SLIsolatedStorage.zip (30.84 KB)
  Posted on: Sunday, December 20, 2009 12:26:40 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 19, 2009    

The day before yesterday, we looked at an sample with Twitter: we retrieved the tweets from the public timeline in an OOB trusted application. The public timeline feed on Twitter requires no credentials to be passed along. Some other feeds however do, such as the user timeline (containing your own tweets) and the friends timeline (containing the tweets of your friends).

Up until Silverlight 4, passing credentials to a service was not supported. Silverlight 3 added support for the ClientHttp stack, however, it was not possible to modify the authorization header, resulting in it being impossible to pass credentials. Silverlight 4 adds this support however. In combination with the support for cross-domain access for services for Silverlight if they are executed with elevated permissions, we can easily build a more complete Twitter client in Silverlight. We already did some work on this application, we will now extend it to make it possible to execute requests to services that require authorization.

Below is a screenshot of the modified application, running OOB as a trusted application.

image

We will not be looking at the code for the public timeline, that was already covered two days ago. Instead, let’s focus on the code we need to write to make the authorized request possible. Of course, we need the user’s credentials, therefore, I added a username/password field.

When clicking on the Submit button, two request are being executed:

Here’s the code for the first one. Note a few things. Passing credentials is only possible if using the ClientHttp stack. This is enabled by WebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp). This selects the ClientHttp stack instead of the browser http stack, which is used by default. To pass the credentials, we use the Credentials property and set it to an instance of NetworkCredentials. Here’s the code.

WebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
//try finding the user tweets and friends tweets
string userTimeLine = "http://twitter.com/statuses/user_timeline/" + 
  UserNameTextBox.Text + ".xml";
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(UserNameTextBox.Text, 
  PasswordTextBox.Password);
client.UseDefaultCredentials = false;
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler
  (user_DownloadStringCompleted);
 
client.DownloadStringAsync(new Uri(userTimeLine, UriKind.Absolute));

A very important line is setting the UseDefaultCredentials to false. If we set it to true, Silverlight will pass the credentials of the logged-on user on the machine (NTLM). If this is the wanted behavior however, simply setting this property to true will of course enable this.

The complete code for this application can be downloaded here:

SLTwitterCredentials.zip (82.89 KB)
  Posted on: Saturday, December 19, 2009 9:24:22 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 18, 2009    

After looking at Twitter yesterday, we have arrived at another data binding-related feature new in Silverlight 4, namely the support for the IDataErrorInfo interface.

The fact that Silverlight supports this interface now, means we can fully use it to help with the display of validation errors in a data binding scenario. The interface itself is quite simple, as shown below:

public interface IDataErrorInfo
{
    string Error { get; }
 
    string this[string columnName] { get; }
}

When we are binding an object of a class that implements the IDataErrorInfo, Silverlight will automatically check each field for validation errors using the indexer. In here, we can write validation code that will check if the specified value is valid and if not, return the error message for that field. Silverlight will then automatically display the error for the field.

I have created a small sample that does exactly that. Being it almost Christmas, I have created a sample where the user can enter his christmas music collection, as shown below.

image

The type we are binding to is called ChristmasSong. This class implements both the INotifyPropertyChanged and the IDataErrorInfo interfaces. Both have been implemented in the code below. In the indexer, we are checking per column if the entered value is valid. If not, we are returning a message containing the validation error. Note that when we are entering “Last Christmas” by “Wham”, the application will not accept it! (Sorry to all Wham fans ;-) )

public class ChristmasSong : IDataErrorInfo, INotifyPropertyChanged
{
    private string title;
    private string performedBy;
    private TimeSpan duration;
    private DateTime published;
 
    private string error;
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
 
    public string Title
    {
        get
        {
            return title;
        }
        set
        {
            title = value;
            NotifyPropertyChanged("Title");
        }
    }
 
    public string PerformedBy
    {
        get
        {
            return performedBy;
        }
        set
        {
            performedBy = value;
            NotifyPropertyChanged("PerformedBy");
        }
    }
 
    public TimeSpan Duration
    {
        get
        {
            return duration;
        }
        set
        {
            duration = value;
            NotifyPropertyChanged("Duration");
        }
    }
 
    public DateTime Published
    {
        get
        {
            return published;
        }
        set
        {
            published = value;
            NotifyPropertyChanged("Published");
        }
    }
 
    public string Error
    {
        get { return error; }
    }
 
    public string this[string columnName]
    {
        get 
        {
            string error = string.Empty;
            switch (columnName)
            {
                case "Title":
                    if(string.IsNullOrEmpty(title))
                        error = "Title can not be blank";
                    break;
                case "PerformedBy":
                    if(string.IsNullOrEmpty(performedBy))
                        error = "The artist should be filled in";
                    else if(performedBy.Equals("Wham") && title.Equals("Last Christmas"))
                        error = "You should NOT be entering that song to your collection!";
                    break;
                case "Duration":
                    if(duration.TotalSeconds > 600)
                    error = "A song can not be longer than 10 minutes";
                    break;
                case "Published":
                    if (Published > new DateTime(2010, 1, 1))
                        error = "You found a song from the future?";
                    else if (published < new DateTime(1900, 1, 1))
                        error = "That's a bit too old, isn't it?";
                    break;
            }
            return error;
        }
    }
}

We can now bind our UI to an instance of this type. Below is the XAML code for the Grid containing the fields. Note especially the data binding expression, where I’m stating the fields should be reporting the error back. For spacing reasons, I only pasted the Title field, the others are similar.

<TextBlock x:Name="TitleTextBlock" Text="Title" Grid.Row="1"  
  Foreground="Red" HorizontalAlignment="Left" Margin="2" 
  VerticalAlignment="Center"></TextBlock>
<TextBox x:Name="TitleTextBox" Grid.Row="1" Grid.Column="1" Width="200" 
  VerticalAlignment="Center" HorizontalAlignment="Left" Margin="2" 
  Text="{Binding Path=Title, Mode=TwoWay, ValidatesOnDataErrors=True, 
    NotifyOnValidationError=True}" />

When we are entering data now, the validation will kick in whenever a validation error is encountered.

We can take it one step further though, using the BindingValidationError event, defined on FrameworkElement. This event will trigger whenever a binding error is reported by the binding source, being here the instance of the ChristmasSong class. In this event, we can through the e.Action property check if an error was added or resolved. In this particular code, I have specified that the Submit button will only become enabled when there are no more errors.

private void ChristmasSongGrid_BindingValidationError(object sender, 
  ValidationErrorEventArgs e)
{
  switch (e.Action)
  {
    case ValidationErrorEventAction.Added:
         errorsOnPage++;
         break;
    case ValidationErrorEventAction.Removed:
         errorsOnPage--;
         break;
  }
  if (errorsOnPage == 0)
    SubmitButton.IsEnabled = true;
  else
    SubmitButton.IsEnabled = false;
}

All this can be seen in action, when we are entering “Last Christmas” by “Wham”!

image

The sample code can be downloaded here: SLDataErrorInfo.zip (308.96 KB)

  Posted on: Friday, December 18, 2009 12:06:56 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 17, 2009    

In today’s article, we’re looking at cross-domain access to a service in Silverlight 4’s trusted applications.

As you may know, when accessing any service located in a domain different from the one in which the Silverlight application itself is hosted, Silverlight will check for a cross domain file being in place. Cross-domain policies prevent Silverlight applications to connect with services that are not in the same domain. However, a service can opt-in to be connected to if at the root of the domain, a cross-domain policy file has been deployed. Silverlight will check for its existence (the file should be named clientaccesspolicy.xml or crossdomain.xml, which is the cross-domain file of Flash) and if found, Silverlight will connect in a cross-domain manner.

Services such as Twitter and Facebook do not deploy this file anymore. Flickr does, meaning that we can connect to Flickr from a client-side Silverlight application. If we want to connect with Twitter from Silverlight, we have to create a service within the same domain as where the Silverlight application is hosted. This service can then communicate with Twitter and Silverlight can communicate with our service.

In Silverlight 4, the notion of trusted applications was added (we looked in this blog series already to some other concepts available when running a trusted application such as COM interop and local file access). If a Silverlight application is running as a trusted application, it can perform cross-domain calls, without there needing to be a cross domain policy file in place. That means that we can build a Twitter client as a trusted Silverlight application without having to build an extra service layer in between.

In the sample I have built for this post, I’m doing exactly that. Below is a screenshot. The UI of the application contains a templated ListBox. Note that the application is running OOB as a trusted application.

image

The code for this application is quite easy. It’s the same code we would write to access a “local” service, meaning a service in the same domain. Below is the code to access Twitter, an asynchronous web service call using the WebClient class.

public void GetPublicTimeLine()
{
    string publicTimeLine = "http://twitter.com/statuses/public_timeline.xml";
    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler
      (client_DownloadStringCompleted);
    client.DownloadStringAsync(new Uri(publicTimeLine, UriKind.Absolute));
}
 
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    XDocument document = XDocument.Parse(e.Result);
    twitterData = (from status in document.Descendants("status")
                   select new Tweet
                   {
                     Message = status.Element("text").Value.Trim(),
                     User = status.Element("user").Element("name").Value.Trim()
                     }).ToList();
 
    PublicTimeLineListBox.ItemsSource = twitterData;
}

This code is executed when a user clicks on the “Load Twitter Messages” button at the top. We do perform a check to see if the application is running OOB and is running with elevated permissions.

private void LoadTwitterButton_Click(object sender, RoutedEventArgs e)
{
    if (Application.Current.IsRunningOutOfBrowser && 
            Application.Current.HasElevatedPermissions)
    {
        //it's OK to access Twitter services cross domain now
        GetPublicTimeLine();
    }
}

Tomorrow, we will look at extending this sample by allowing to send credentials to Twitter to access personalized streams of tweets.

The complete sample can be downloaded here.

SLTrustedTwitter.zip (269 KB)
  Posted on: Thursday, December 17, 2009 4:52:54 PM (Romance Standard Time, UTC+01:00)   |   Comments [3]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 16, 2009    

The DataGrid is probably the most popular control in many business applications. Added in Silverlight 2, this control allows for easy displaying and editing of data in a tabular format. While already a very decent control, the DataGrid in Silverlight 2 and 3 still had some things that were missing or not working like you’d hope them to. In today’s post, we’ll look at the newly added changes to the control.

The first and probably biggest change is the auto-sizing option for columns. In previous versions, we could basically specify a column width or specify nothing at all, leaving it to Silverlight. What we could not do, was saying to a specific column: Take all the remaining space, similar to what we can do with the Grid control through the use of *.

Basically, there are now 5 options we have to specify how a column should behave (copied from the MSDN docs):

Member name
Description
Auto
The unit of measure is based on the size of the cells and the column header.
Pixel The unit of measure is expressed in pixels.
SizeToCells The unit of measure is based on the size of the cells.
SizeToHeader The unit of measure is based on the size of the column header.
Star The unit of measure is a weighted proportion of the available space.

Let’s take a look at using these in an example. I created a random data generator (see sample code download), which generates Employee instances. These are stored in a generic list which is then set as the ItemsSource for a DataGrid. The result can be see below.

image

As you can see in the screenshot, the Address column is wider than the others. I actually specified it to be twice as wide as the FirstName and the LastName columns. The City column has a specific width set.

<data:DataGrid AutoGenerateColumns="False" x:Name="EmployeeDataGrid" 
    HeadersVisibility="All" Grid.Row="1">
    <data:DataGrid.Columns>
        <data:DataGridTextColumn Header="FirstName" Binding="{Binding FirstName}" Width="*"/>
        <data:DataGridTextColumn Header="LastName" Binding="{Binding LastName}" Width="*"/>
        <data:DataGridTextColumn Header="Address" Binding="{Binding Address}" Width="2*"/>
        <data:DataGridTextColumn Header="City" Binding="{Binding City}" Width="100" />
    </data:DataGrid.Columns>
</data:DataGrid>

We can also use the other options. By clicking on the Change button at the top, we switch the DataGrid to use another sizing option.

private void ChangeColumnsButton_Click(object sender, RoutedEventArgs e)
{
    EmployeeDataGrid.Columns[0].Width = new DataGridLength(1, 
        DataGridLengthUnitType.SizeToCells);
    EmployeeDataGrid.Columns[1].Width = new DataGridLength(1, 
        DataGridLengthUnitType.SizeToCells);
    EmployeeDataGrid.Columns[2].Width = new DataGridLength(1, 
        DataGridLengthUnitType.SizeToCells);
    EmployeeDataGrid.Columns[3].Width = new DataGridLength(1, 
        DataGridLengthUnitType.Star);
}

This results in the following:

image

The first three columns are sizing to their contents. The City column takes all the remaining space.

The second new feature concerning the DataGrid, is the ability to copy data from the DataGrid to Excel. This feature is really handy in business applications. Very often, we need to be able to export data from an application towards Excel. This can make this very easy to do.

When we start a copy by selecting one or more rows, we are shown a prompt, asking us if we want to allow access to the clipboard. If confirmed, the data is copied as textual information and can be pasted in Excel.

There’s an event fired per row that is copied to the clipboard, namely the CopyingRowClipboardContent event. In this event, we can see what data is being copied and if needed apply transformations on it.

private void EmployeeDataGrid_CopyingRowClipboardContent(object sender, 
    DataGridRowClipboardEventArgs e)
{
    // do something
}
The complete sample can be downloaded here. SLNewDataGrid.zip (1.04 MB)
  Posted on: Wednesday, December 16, 2009 10:10:05 PM (Romance Standard Time, UTC+01:00)   |   Comments [2]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 15, 2009    

In today’s article, we’ll be looking at another new feature that was added with Silverlight 4, namely the ability to react to right-clicks in a Silverlight application. This means that we can override the default behavior of Silverlight where it’s showing the context menu allowing us to go to the configuration screen.

Because Silverlight now supports right-clicking, we can create a context menu that appears on the right-click event. We can code this context menu as we want. Right-clicking is supported on any UIElement: on the UIElement class, there are two new events added, namely the MouseRightButtonDown and the MouseRightButtonUp. Both of these new events use MouseButtonEventArgs as their event arguments, which are also used for the normal left click events.

As said, by default, the Silverlight context menu is shown when a user right-clicks on a Silverlight application. To block this, in the MouseRightButtonDown, we have to set the e.Handled to true. This way, the default context menu is not shown and we can go ahead and create our own context menu. This will appear on the MouseLeftButtonUp event.

Let’s take a look at a simple application. In this application, we have attached a custom context menu on an Image control. Using this context menu, I can choose to delete the image I clicked on.

image

The image itself has both the MouseRightButtonDown and the MouseRightButtonUp events attached to it using XAML code:

<Image Height="195" x:Name="imgTree" Stretch="Fill" Width="249" 
   MouseRightButtonDown="imgTree_MouseRightButtonDown" 
   MouseRightButtonUp="imgTree_MouseRightButtonUp" 
   Source="tree.png" Canvas.Left="181" Canvas.Top="79">
</Image>

To prevent the default context menu from appearing, we can set the e.Handled to true in the mouse down event:

private void imgTree_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    e.Handled = true;
}

In the mouse up event, we can then specify what context menu we want to have appear:

private void imgTree_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    Image image = sender as Image;
    if (image != null)
    {
        ContextMenu contextMenu = new ContextMenu(PrintCanvas, image);
        contextMenu.Show(e.GetPosition(LayoutRoot));
    }
}

The ContextMenu used here is a custom control.

The complete source code can be downloaded here: SLRightClick.zip (473.2 KB)

  Posted on: Tuesday, December 15, 2009 11:21:21 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 14, 2009    

Only 10 days ‘till Christmas and thus only 10 more posts after this one to finish my series. In today’s post, we’ll be taking a look at the Local Connection API, a feature introduced with Silverlight 3.

Most of the time, we build full-screen Silverlight applications, meaning that the only function that the HTML still fulfills, is hosting a DIV that will contain the HTML OBJECT tag in which Silverlight will be hosted. However, sometimes Silverlight could be used as an “island” on an HTML page. For example, we could have an HTML page (perhaps rendered by ASP.NET) in which a table of data is shown. The end-user may want a richer experience with this data grid such as reordering rows, efficient paging and so on. We could decide to just convert that specific part to functionality to Silverlight, resulting in a Silverlight island.

To go even further, in some scenarios, it may be needed that two or more of these Silverlight islands live on a single page. Silverlight 2 introduced the HTML Bridge to allow these two Silverlight plug-ins to talk to one another: using Javascript as an intermediate, we could send messages from control 1 to control 2 and vice-versa. While possible, it’s not the easiest way of developing an application.

Silverlight 3 introduced something easier for this particular problem, namely the local connection API. It basically allows two or more Silverlight instances to communicate with each other. These two instances can live on the same page, but can even live on two different browser tabs or even two different browser windows. The API uses a concept of a named pipe: a named sender sends a message into a pipe and a receiver can intercept this message. The message needs to be a string.

The messaging system introduced is based on two types, LocalMessageSender and LocalMessageReceiver, both types that live in the System.Windows.Messaging namespace.

Let’s take a look at an example. The application I built for this post contains two Silverlight controls. The first control contains a few buttons. When clicking on a button, I want to change the background of control n° 2. (Note that these are actually 2 different Silverlight applications hosted on one single page).

image

The first thing we need to do is creating an instance of the LocalMessageSender class. As parameter, we pass in the name that will be used as the identification (ColorSender), like so:

private LocalMessageSender localMessageSender;
private LocalMessageReceiver localMessageReceiver;
 
public MainPage()
{
    InitializeComponent();
    localMessageSender = new LocalMessageSender("ColorSender");
 
}

When we click on a button, we’ll send a message using this instance. In this case, we pass in the name of the color we want:

private void RedButton_Click(object sender, RoutedEventArgs e)
{
  localMessageSender.SendAsync("Red");
}
 
private void GreenButton_Click(object sender, RoutedEventArgs e)
{
  localMessageSender.SendAsync("Green");
}
 
private void BlueButton_Click(object sender, RoutedEventArgs e)
{
  localMessageSender.SendAsync("Blue");
}

In the second application, we create a LocalMessageReceiver, passing in the same string, ColorSender, as the name of the sender it should listen to. We then specify the handler for the MessageReceived event, which will trigger when a string is received. The receiver starts listening for values by calling its Listen() method:

private LocalMessageReceiver localMessageReceiver;
 
public MainPage()
{
  InitializeComponent();
  localMessageReceiver = new LocalMessageReceiver("ColorSender");
  localMessageReceiver.MessageReceived += 
  new EventHandler<MessageReceivedEventArgs>(localMessageReceiver_MessageReceived);
  localMessageReceiver.Listen();
}

Based on the value of the received message, we change the color:

void localMessageReceiver_MessageReceived(object sender, MessageReceivedEventArgs e)
{
  switch (e.Message)
  {
    case "Red": LayoutRoot.Background = new SolidColorBrush(Colors.Red);
                ColorTextBlock.Text = "RED";
                break;
    case "Green": LayoutRoot.Background = new SolidColorBrush(Colors.Green);
                  ColorTextBlock.Text = "GREEN";
                  break;
    case "Blue": LayoutRoot.Background = new SolidColorBrush(Colors.Blue);
                 ColorTextBlock.Text = "BLUE";
                 break;
    default: LayoutRoot.Background = new SolidColorBrush(Colors.White);
             ColorTextBlock.Text = "WHITE";
             break;
  }
}

The code can be downloaded here: SLLocalConnection.zip (97.1 KB)

  Posted on: Monday, December 14, 2009 9:31:33 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     Silverlight | Silverlight Advent Calendar | sl4     December 14, 2009    

I hope you are all enjoying my post series Silverlight Advent Calendar. I still have a list of upcoming articles, but I was wondering, are there any specific things you would like to see appear?

I have one request already for an article on the local connection API, that will come in the coming days.

Let me know your ideas!

  Posted on: Monday, December 14, 2009 8:57:06 AM (Romance Standard Time, UTC+01:00)   |   Comments [4]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 13, 2009    

In today’s post, we will be working with services. As some of you know, I’m currently finishing my first book titled Silverlight 4 Data Access Cookbook. If all goes well, it will be available in early access preview somewhere in the coming week. Therefore, I decided I needed to write a post that’s in the same area as my book. More specifically, I’ll be creating a application that works together with the services API exposed by Bing.com, Microsoft’s new and successful search engine.

Bing has a very rich API that we can use to incorporate search functionalities in our applications, including Silverlight applications. It allows us to use WCF (SOAP) and REST communication, because it exposes endpoints for both these technologies. In this particular example, I’m using the SOAP interface for communication using a WCF service. To get a complete overview of the functionalities, you can download the PDF describing the entire API at http://www.bing.com/developers/s/API%20Basics.pdf . It also contains some sample code.

The very first thing we should before we can actually start building applications with Bing, is obtaining an API key. This key is required so Bing can check that your request is valid (this key will be part of every request you’ll send to Bing). Obtaining a key is free and can be done at http://www.bing.com/developers/createapp.aspx .

The provided sample is a Silverlight 4/VS2010 solution, all the code included however also works with Visual Studio 2008/Silverlight 3.

First, we need to generate a proxy using Visual Studio 2010. For this, we need the address of the WSDL (Web Service Description Language) file. In the documentation, we can find that this address is: http://api.search.live.net/search.wsdl?AppID=12345 where 12345 needs to be replaced with your obtained API key. In Visual Studio, we add the service reference using the dialog and I have set the namespace to BingSearchService.

image

Visual Studio will at this point create the proxy for the service. A proxy contains a client-side copy of the types exposed by the service and its methods. The contents of the methods is replaced with a call to the real service method. In the client-side code, we can now work with these types and methods.

In the screenshot a bit further, you can see the interface of the application. It contains a TextBox and a Button to search and a templated ListBox to display the results. Let’s first create the code for the event handler of the click event. Bing accepts quite a lot of parameters for the search it needs to perform. These are encapsulated in an object of type SearchRequest. Since we are conducting a normal web search, we specify this in the Sources property of the SearchRequest instance. A search with Bing is a service request, so all communication needs to be done asynchronously. We can see this at the way we are calling the service using the SearchCompleted event and SearchAsync() method. Below is the code.

private void SearchButton_Click(object sender, RoutedEventArgs e)
{
  LiveSearchPortTypeClient soapClient = new LiveSearchPortTypeClient();
  SearchRequest request = new SearchRequest();
  request.AppId = "81691C6A195FBC3FB469594BAA30B50A99CF3D22";
  request.Sources = new SourceType[] { SourceType.Web };
 
  if (SearchTextBox.Text != string.Empty)
  {
    request.Query = SearchTextBox.Text;
    soapClient.SearchCompleted += 
      new EventHandler<SearchCompletedEventArgs>(soapClient_SearchCompleted);
    soapClient.SearchAsync(request);
  }
}

When the service completes asynchronously, meaning, when Bing’s results are ready and available, the *Completed event is called and executed. In this event handler, we have access to the results of the service call. The result can be found in the e.Result parameter and is always of the same type as returned by the service. In our specific case, the used type is a SearchResponse, again a type exposed by the Bing services. We can now loop through these results and using a simple LINQ query, create an IEnumberable<SearchResult> . SearchResult is a type created by us to allow us to data bind to the results. This type is very simple:

public class SearchResult
{
    public string SearchResultTitle { get; set; }
    public string SearchResultDescription { get; set; }
    public string SearchResultUri { get; set; }
}

The code for the event handler is shown next:

void soapClient_SearchCompleted(object sender, SearchCompletedEventArgs e)
{
    SearchResponse response = e.Result;
    if (response.Web.Results.Count() > 0)
    {
        var results = from result in response.Web.Results
                      select new SearchResult
                      {
                          SearchResultTitle = result.Title,
                          SearchResultUri = result.Url,
                          SearchResultDescription = result.Description
                      };
        ResultListBox.ItemsSource = results.ToList();
    }
}

The ListBox is as said templated; the ItemsTemplate has been replaced with a custom data template, as shown below:

<ListBox x:Name="ResultListBox" Grid.Row="1" Margin="3" Background="Black">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="{Binding SearchResultTitle}" FontWeight="Bold" 
          FontSize="15" TextDecorations="Underline" Foreground="White"></TextBlock>
        <TextBlock Text="{Binding SearchResultDescription}" Grid.Row="1" 
          TextWrapping="Wrap" Width="400" HorizontalAlignment="Left" 
          Foreground="White"></TextBlock>
        <TextBlock Text="{Binding SearchResultUri}" Grid.Row="2" Foreground="#568e71">
        </TextBlock>
      </Grid>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

When we now execute a search using our application, we see the following:

image

The complete sample can be downloaded here:

SLBing.zip (790.49 KB)
  Posted on: Sunday, December 13, 2009 12:48:53 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 11, 2009    

I made it through the first half of my Silverlight Advent Calendar! You’re currently reading the 12th installment of my article series. In this article, we are looking at the RichTextArea control, which was added to the platform with Silverlight 4.

Up until Silverlight 4, we had no real way to perform rich text editing. Some (open source) implementations have been built of which the best one is in my opinion VectorLight.com’s RichTextBox/RichTextBlock (check it out at www.vectorlight.com, they have quite some nice controls). Silverlight 4 introduces the RichTextArea control. Its name already implies what it is capable of: allowing us to do rich text editing in our Silverlight applications. Things like making text bold, italic or underlined are of course supported by this control. On top of that, more advanced options are available, such as adding hyperlinks in text, adding images and adding XAML content. It can also out-of-the-box work with the clipboard and offers BiDi support. The latter is important for some languages such as Hebrew, since these are right-to-left languages.

Behind the visual of the control, text is being added as XAML, so in fact, the control is rendering the result of that XAML. This XAML is XAML like we know it for displaying rich text using TextBlock controls, containing Paragraphs, Runs and LineBreaks. At the time of writing, there is no real Text property on the control to get the entered text without the markup. To get the contents, we can use the Blocks collection to loop through the content. This is a bit of a setback and I can only hope it will in some way become possible to get the text from the control as well (without the markup).

Using this new control, we can thus perform most of the actions we’ll want to do with text. The control does not have buttons by default, so we need to add them ourselves. Below is an implementation of the control in combination with a ribbon (found in the official Silverlight 4 whitepaper/documentation).

image

Let’s take a look a simple implementation now. My implementation will make it possible to add text (quite logically), make it bold, underlined or italic. We’ll also add the possibility to change the color of the selected text and print it using the new printing functions in Silverlight 4.

image

Below is the XAML for the RichTextArea (nothing special as you can see):

<RichTextArea x:Name="MainRichTextArea" Height="300"></RichTextArea>

To implement the different functions, we need to add some code in the event handlers of the button click events. For example, if we want to make the selected text bold, we start by checking if text is selected. If there is, we check if the selected text is already bold or not. We set it to bold if it isn’t and vice-versa of course. The code for this is shown below.

private void BoldButton_Click(object sender, RoutedEventArgs e)
{
  if (MainRichTextArea.Selection.Text.Length > 0)
  {
    if (MainRichTextArea.Selection.GetPropertyValue(Run.FontWeightProperty) 
        is FontWeight &&
        ((FontWeight)MainRichTextArea.Selection.GetPropertyValue
        (Run.FontWeightProperty)) == FontWeights.Normal)
        {
          MainRichTextArea.Selection.SetPropertyValue(Run.FontWeightProperty, 
            FontWeights.Bold);  
        }
    else
        MainRichTextArea.Selection.SetPropertyValue(Run.FontWeightProperty, 
          FontWeights.Normal);
        MainRichTextArea.Focus();
    }
}

The code is similar for the other actions, it can be found in the sample code download. When we want to print our added text, we have 2 options. The most simple one is pointing the PageVisual to the RichTextArea:

private void PrintButton_Click(object sender, RoutedEventArgs e)
{
  PrintDocument printDocument = new PrintDocument();
  printDocument.DocumentName = "My rich text";
 
  printDocument.PrintPage += (s, args) =>
  {
    args.PageVisual = MainRichTextArea;
  };
  printDocument.Print();
}

The second option exists out of looping through the Blocks collection of the RichTextArea, parsing each of the retrieved items and adding them to the Inlines collection of a TextBlock control.

The sample code can be downloaded here: SLRichTextArea.zip (84.68 KB)

  Posted on: Saturday, December 12, 2009 12:49:28 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 11, 2009    

One day away from finishing the first 12 (half of the total of 24 ;-) )of my Silverlight articles. In this post, we are looking at local file access in Silverlight 4. This new feature is another one that is only enabled with OOB apps with elevated permissions.

In Silverlight 2 and 3, we already had some basic file access. We could perform an OpenFileDialog starting with Silverlight 2. It gave us a read-only stream to the selected file, meaning that the only thing we could do with the file, was reading it and using its contents in the application. Silverlight 3 added the SaveFileDialog, which, surprisingly, allows us to save files to the local disk.

Silverlight 4 ads more or less real local data access. By more or less, I mean that Silverlight applications can only access some folders. More particularly, we can access the My Documents, My Pictures, My Videos and My Music folders (on Mac, an equivalent exists). Within this directory, we can read, create and delete files. One important side-note though: the application needs to be a trusted application, meaning that it needs to run with elevated permissions.

Silverlight has a specific enumeration that we can use to get the physical location of the files: Environment.SpecialFolder. In it, we can find MyPictures etc. Note that it contains more than what we can access at this point, for example ProgramFiles. Even if we try to do something with this, we can’t since Silverlight won’t allow access to this directory.

Let’s take a look at a basic application as shown below.

image

Let’s first take a look at the left listbox, which is filled with the files of my My Pictures folder. Reading out the files, as well as other operations on the files, are done using the traditional classes contained in the System.IO namespace, such as Directory, File, Path etc. To read out the contents, we use the following code:

if (canWork)
{
  var files = Directory.EnumerateFiles(Environment.GetFolderPath
   (Environment.SpecialFolder.MyPictures));
  foreach (var file in files)
    {
      string fileName = System.IO.Path.GetFileName(file);
      imageNames.Add(fileName);
    }
    ImageListBox.ItemsSource = imageNames;
}

Note the canWork bool value. Since the application can only work if running OOB and with elevated permissions, we perform a check initially to see if the operations are permitted. The value is set through the following code:

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
  //check to see if application is running OOB and with elevated permissions
  if (App.Current.IsRunningOutOfBrowser && App.Current.HasElevatedPermissions)
    canWork = true;
  else
    MessageBox.Show("The application needs to run out-of-browser with 
      elevated permissions");
}

The second listbox is filled with all *.txt files, located in my My Documents folder: I’m simply applying a filter.

private void FetchTextFiles()
{
    var files = Directory.EnumerateFiles(Environment.GetFolderPath
     (Environment.SpecialFolder.MyDocuments))
     .Where(filename => filename.EndsWith("txt"));
    
    TextFilesListBox.ItemsSource = files;
}

As said, we can do more than just reading out the contents of a directory. We can for example delete a file. When we select a file in the second listbox, we can delete it using the following code:

private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
  if (canWork)
  {
    if (TextFilesListBox.SelectedItem != null)
    {
      string path = TextFilesListBox.SelectedItem.ToString();
      File.Delete(path);
      FetchTextFiles();
    }
  }
}

As you can see, working with the files is no different than working with files in plain .NET.

The code can be downloaded here: SLLocalFileAccess.zip (68.26 KB)

  Posted on: Friday, December 11, 2009 10:34:42 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 10, 2009    

Today, we are looking again at another new feature in Silverlight 4 which is the support for webcams and microphones.

Silverlight 4 gets support for microphones and webcams. It has access to the raw streams for both. The added support opens a lot of opportunities for new types of applications. For example, it becomes possible to write an application that reads barcodes of products you hold in front of the webcam, scans them and searches for product information.

The classes that expose this functionality live in the System.Windows.Media namespace. We’ll be using those to create a simple application that connects with the webcam and takes snapshots. Below is the interface of the application (a colleague of mine was just eating a banana :) )

image

The XAML for the application is shown below. The ComboBox displays the available webcams (only one on my machine), we are binding to the FriendlyName property. The ListBox is templated: both the ItemsTemplate and the ItemsPanel are overriden, to have the control display a horizontal list of images.

<Grid x:Name="LayoutRoot" Background="White">
  <Grid.RowDefinitions>
    <RowDefinition Height="330"></RowDefinition>
      <RowDefinition Height="50"></RowDefinition>
        <RowDefinition Height="140"></RowDefinition>
  </Grid.RowDefinitions>
  <Border BorderBrush="Black" BorderThickness="3" HorizontalAlignment="Center" 
    VerticalAlignment="Center">
    <Rectangle x:Name="WebcamRectangle" Fill="LightGray" Height="300" 
      Width="400"></Rectangle>
  </Border>
  <StackPanel Orientation="Horizontal" Grid.Row="1" VerticalAlignment="Center" 
    HorizontalAlignment="Center">
    <ComboBox x:Name="WebcamComboBox" Width="200" Margin="3" 
      SelectionChanged="WebcamComboBox_SelectionChanged">
      <ComboBox.ItemTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding FriendlyName}"></TextBlock>
        </DataTemplate>
      </ComboBox.ItemTemplate>
    </ComboBox>
    <Button x:Name="StartWebcamButton" Click="StartWebcamButton_Click" 
      Content="Start webcam" HorizontalAlignment="Center" Margin="3"></Button>
    <Button x:Name="TakePictureButton" Click="TakePictureButton_Click" 
      Content="Take picture" HorizontalAlignment="Center" Margin="3"></Button>
  </StackPanel>
  <ListBox x:Name="PicListBox"  Width="500" Height="120" 
    ScrollViewer.HorizontalScrollBarVisibility="Visible"  Grid.Row="2">
    <ListBox.ItemTemplate>
      <DataTemplate>
        <Image Margin="5" Source="{Binding}" Stretch="UniformToFill" 
          Height="80" VerticalAlignment="Center"/>
      </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top" 
          HorizontalAlignment="Left"/>
      </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
  </ListBox>
</Grid>

To fill the ComboBox with the available webcams, we can use the CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices(). This returns a Collection of VideoCaptureDevice instances. The VideoCaptureDevice class exposes the FriendlyName property we used in the data binding expression.

//fills the dropdown with all available webcams
WebcamComboBox.ItemsSource = 
  CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();

We can instruct Silverlight to use the default capturing device, if nothing is selected by the user in the ComboBox:

//use the default
VideoCaptureDevice selectedVideoCaptureDevice = 
CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();

A little side note: we can change the default device in the Silverlight Configuration window as shown below.

image

Starting the webcam needs to be a user-initiated action. It’s impossible to start the webcam on load of the application for example. Therefore, we put this code in the event handler of the click on the Button. Whenever the webcam is started, a prompt is shown, asking the user if he wants to allow the application to access the device. This prompt can not be changed by the developer.

image

The following lines of code, located in the click event handler, check if the user has already granted permission in this particular session to access the webcam. If not, the prompt is shown following the RequestDeviceAccess() method call.

if (CaptureDeviceConfiguration.AllowedDeviceAccess 
    || CaptureDeviceConfiguration.RequestDeviceAccess())
{
...
}

To access the video capture of the webcam, we use the CaptureSource class.

VideoCaptureDevice videoCaptureDevice = selectedVideoCaptureDevice;
CaptureSource captureSource = new CaptureSource();
captureSource.VideoCaptureDevice = videoCaptureDevice;

This CaptureSource can then be used in combination with a VideoBrush to paint the video on any shape. Here, we used a Rectangle. To start the capturing of the device associated with the capture device (note that more than one device can be associated with one CaptureSource), we call its Start() method.

VideoBrush videoBrush = new VideoBrush();
videoBrush.SetSource(captureSource);
WebcamRectangle.Fill = videoBrush;
captureSource.Start();

If we want to capture a snapshot, we can use the AsyncCaptureImage method. It provides a WriteableBitmap to the Action(T) which is passed in as parameter. We add the image to the collection. Because of the applied binding, it is displayed automatically.

private void TakePictureButton_Click(object sender, RoutedEventArgs e)
{
    captureSource.AsyncCaptureImage((snapshot) =>
    {
        snapshots.Add(snapshot);
    });
}

The complete code for today’s article can be found here: SLWebcam.zip (60.67 KB)

  Posted on: Thursday, December 10, 2009 11:33:15 AM (Romance Standard Time, UTC+01:00)   |   Comments [1]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 9, 2009    
Article number 9 is here, a bit later on the day since I was home late yesterday from the MVP dinner we had and left at 6am this morning to do the Silverlight Road Show. But here we are with the article of today, December 9th!

Today we are looking at a data binding feature that was introduced with Silverlight 3. The reason I’m dedicating an article to it, is that not that many people seem to know about this little gem, namely element-to-element binding or simply element binding. Regular data binding happens between a source object (for example a Person or a Customer) and a control such as a TextBlock. Element binding happens between 2 controls: a property of element A is bound to a property of element B.

A good example to understand element bindings is the following: a Slider control of which the Value property is bound to the Text property of a TextBlock.

image

To make the link between the 2 values, we create a binding as usual, but we specify the “source” as being another element, in this case the Slider control using the ElementName property on the binding.

<StackPanel x:Name="SliderStackPanel" Orientation="Horizontal" Grid.Row="0">
    <Slider x:Name="YearsToPensionSlider" Width="300" Minimum="0" Maximum="40" 
      SmallChange="1" LargeChange="1" VerticalAlignment="Center"></Slider>
    <TextBlock x:Name="ValueTextBlock" 
      Text="{Binding ElementName=YearsToPensionSlider, Path=Value}" 
      VerticalAlignment="Center"></TextBlock>
</StackPanel>

We can also make this binding a bi-directional binding. In the image above, in the second row, it’s possible to specify a value manually in the TextBox control. Due to the binding, the slider will also change its value if we specify the binding to be a two way binding, as so:

<StackPanel x:Name="SliderStackPanel2" Orientation="Horizontal" Grid.Row="1">
    <Slider x:Name="YearsToPensionSlider2" Width="300" Minimum="0" Maximum="40" 
      SmallChange="1" LargeChange="1" VerticalAlignment="Center"></Slider>
    <TextBox x:Name="ValueTextBox" 
      Text="{Binding ElementName=YearsToPensionSlider2, Path=Value, Mode=TwoWay}" 
      VerticalAlignment="Center" Width="100"></TextBox>
</StackPanel>

You can download the code for this sample here. This is a Visual Studio 2008 project and works both with Silverlight 3 and Silverlight 4.SLElementBinding.zip (59.38 KB)
  Posted on: Wednesday, December 09, 2009 11:35:28 PM (Romance Standard Time, UTC+01:00)   |   Comments [3]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 7, 2009    

Today, I picked another new feature of Silverlight 4, namely the programmatic access to and from the clipboard in Silverlight 4.

Silverlight 4 has the ability to copy text to the clipboard, check if there is text available on the clipboard and paste the text from the clipboard back to the Silverlight application. To support this, it has 3 static methods available on the newly added ClipBoard class:

  • Clipboard.SetText()
  • Clipboard.ContainsText()
  • Clipboard.GetText()

Let’s look at using these in a sample. Below we see the interface of the basic text editing application, containing 2 RichTextArea controls.

image

When clicking on the left button, we check if there’s some text selected in the left RichTextArea control. As said, this is done through the use of the static SetText() method on the ClipBoard class. Note that any interaction with the Clipboard class can only happen after a user-initiated action, such as clicking a Button.

private void CopyButton_Click(object sender, RoutedEventArgs e)
{
    if (CopyTextArea.Selection.Text != string.Empty)
    {
        WarningTextBlock.Text = string.Empty;
        Clipboard.SetText(CopyTextArea.Selection.Text);
    }
    else
    {
        WarningTextBlock.Text = "Select some text first";
    }
}

This call is supported both in-browser and out-of-browser. There’s a difference though. When accessing the clipboard from an in-browser application, a warning will be shown to the user, asking if the action to the clipboard is trusted.

image

If we however make our application a trusted application by requiring elevated permissions when running out-of-browser, it will no longer display this prompt (we looked at elevating permissions yesterday).

When we want to paste in the text using the paste button, we can use the 2 other before mentioned methods, like so:

private void PasteButton_Click(object sender, RoutedEventArgs e)
{
    if (Clipboard.ContainsText())
    {
        PasteTexArea.Selection.Text = Clipboard.GetText();
    }
    else
    {
        WarningTextBlock.Text = "No text exists on the clipboard";
    }
}

In the current beta, we can only copy text to and from the clipboard. Objects such as images are not supported at this point!

The complete code for this sample can be found here: SilverlightClipboard.zip (61.65 KB)

  Posted on: Tuesday, December 08, 2009 12:04:05 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 6, 2009    

December 7th already, this post marks the first week of my Silverlight Advent Calendar!

In today’s post, I’ll be looking at how to create a simple kiosk application. A kiosk application is typically something you see at a booth or a registration desk, filling the entire screen and only allowing the user to perform a specific action. In this specific example, I’m looking at how to create a user registration application which could typically be used for a kiosk.

As said, the most specific requirement for this type of applications, is being full screen. Silverlight 2 and 3 already supported full screen applications: making an application full screen could easily be done using the following line of code:

App.Current.Host.Content.IsFullScreen = true;

This code will only execute following a user-initiated action, such as a click on a Button. It’s thus not possible to load the application full screen by putting this line in some loaded event of the control.

Seems all quite well, doesn’t it? Indeed,  but there was one disappointment in all this: when in full screen, the user could not enter text, the text input was limited to some keys such as the arrow keys. Every character key was ignored. This behavior changed in Silverlight 4. In fact, I should say “can be changed” in Silverlight 4. By default, it will still not accept character keys in full screen, but when creating the application as OOB (Out Of Browser) application and giving it elevated permissions, it will accept them perfectly.

Elevated permissions

Before we look at the application itself, let’s first look at elevated permissions. In Silverlight 1, 2 and 3, code executed  always ran in the sandbox of the browser. There was no way to get out of this sandbox. Silverlight 4 adds a new type of application, namely a trusted Silverlight application, running with elevated permissions and allowing actions that were not possible in the previous versions. This means that we now have 3 possible modes in Silverlight 4: in-browser, out-of-browser (but still in the sandbox) and trusted (out-of-browser with elevated permissions).

Each application can be created to require elevated permissions to run. We can enable this by in the Project Properties window, clicking on the Out-of-Browser settings and then checking the following checkbox:

clip_image002

When the application is now installed, another dialog is displayed, warning the user that this application will have more permissions than “normal” installed apps. This dialog looks like the following screenshot.

image

We’ll come across more features in the following days which require elevated permissions such as COM interop and cross-domain service access.

Back to the kiosk

OK, now that we know that for our application, we’ll need elevated permissions, let’s look at some code and screenshots. The application is built as a navigation application. The application starts (by setting the root page) to an admin screen. In this screen, the admin can set the application to full screen. From then on, it is full screen and cannot be changed by the user.

image

When clicking on the button, the following code is executed:

private void FullScreenButton_Click(object sender, RoutedEventArgs e)
{
    App.Current.Host.Content.IsFullScreen = true;
}

The admin can then click the Start Wizard hyperlink, which will set the kiosk-registration application to its waiting screen.

image

In the following screen, the user can enter his/her details. In full-screen mode, this would NOT have been possible if:

  • we had used Silverlight 2 or Silverlight 3
  • we would not have set the application to require elevated permissions

Try for yourself disabling the elevated permissions requirement. If you run the application in full-screen then (in OOB mode), all text input in the text fields is ignored.

image

How to quit the application

When putting a trusted application in full-screen, by default hitting the ESCAPE key will not resize it back to its original position. Therefore, we can handle the keydown event in the MainWindow.xaml for example, as follows:

private void UserControl_KeyDown(object sender, KeyEventArgs e)
{
    if(e.Key == Key.Escape)
        App.Current.Host.Content.IsFullScreen = false;
}
The full code can be downloaded here: KioskApplication.zip (166.63 KB)
  Posted on: Monday, December 07, 2009 12:08:01 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 3, 2009    

Here we are with the 4th article already in my Silverlight Advent Calendar series!

When using data binding in Silverlight, we often have to include one or more converters. A converter is a class that implements the IValueConverter interface. This class defines 2 methods, Convert and ConvertBack. Convert is applied when the data in the data binding action flows from source object to target control. A common use for converters is formatting a date value that comes from the database into a specific format or adding a currency symbol to a double value. Below is a sample converter class:

public class CurrencyConverter : IValueConverter
    {
 
        #region IValueConverter Members
 
        public object Convert(object value, Type targetType, object parameter, 
            System.Globalization.CultureInfo culture)
        {
            double amount = double.Parse(value.ToString());
            if (amount < 0)
                return "- " + amount.ToString("c", culture);
            else
                return amount.ToString("c", culture);
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, 
            System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
 
        #endregion
    }

Silverlight 4’s data binding engine has been extended with a few options that in some cases can avoid forcing us to create a converter. More specifically, three new options have been added: TargetNullValue, StringFormat and FallbackValue.

For these samples, we’ll use a class called Customer:

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public string Email { get; set; }
}

I have instantiated this class and set it as DataContext for the entire UserControl:

 

customer = new Customer()
           {
               FirstName = "Gill",
               LastName = "Cleeren",
               BirthDay = new DateTime(1979, 1, 1),
               Email = "gillcleeren@somewhere.com",
               CustomerAddress = null
           };
 
           this.DataContext = customer;

Let’s take a look at what these new features offer us. TargetNullValue can be used in a data binding expression to specify what value should be used in case the binding returns null. In the previous sample, there is no value specified for the CustomerAddress property (it is null). If we want some replacement text, in this case “Unknown”, to be placed instead, we can use TargetNullValue like so:

<TextBlock x:Name="AddressTextBlock" Grid.Row="4" Grid.Column="0" 
    Text="Address:" FontWeight="Bold"></TextBlock>
<TextBlock x:Name="AddressValueTextBlock" Grid.Row="4" Grid.Column="1" 
    Text="{Binding CustomerAddress, TargetNullValue=Unknown}" ></TextBlock>

StringFormat can be used to format the value, just as was shown with the Converter earlier. For example, if we want the BirthDay to be formatted as a date in MM/dd/yyyy format, we can do so using the following code:

<TextBlock x:Name="BirthDateTextBlock" Grid.Row="2" 
    Grid.Column="0" Text="Birthday:" FontWeight="Bold"></TextBlock>
<TextBlock x:Name="BirthDateValueTextBlock" Grid.Row="2" Grid.Column="1" 
    Text="{Binding BirthDay, StringFormat=MM/dd/yyyy}"></TextBlock>

Finally, the FallbackValue can be used to display a value when the data-bound property on the source can not be located. In other words, this value will be displayed when we make an error in that we are trying to bind to a non-existent property. This is shown using the following code:

 

<TextBlock x:Name="InfoTextBlock" Grid.Row="5" 
    Grid.Column="0" Text="Info:" FontWeight="Bold"></TextBlock>
<TextBlock x:Name="InfoValueTextBlock" Grid.Row="5" Grid.Column="1" 
    Text="{Binding Info, FallbackValue=Nothing}" ></TextBlock>

The final result is shown below:

image

The complete code sample can be downloaded here: DatabindingInSL4.zip (64.44 KB)

Note: these new data binding features are a Silverlight 4 feature only!

  Posted on: Friday, December 04, 2009 12:02:03 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 2, 2009    

Silverlight is, as you probably know, a web technology. Basically, we have two choices to add Silverlight to a page (be this page ASP.NET, HTML, PHP or what have you):

  • Screen-filling Silverlight application
  • Silverlight “islands”: small piece(s) of Silverlight embedded on a webpage

Silverlight 4 adds a new option for bringing together Silverlight and HTML by means of the WebBrowser control. If you have done WinForms development, you may remember a similar control in that area as well. It basically allows us to display HTML content inside a Silverlight application.

For some scenarios, this is a very interesting addition to the platform. Imagine you are building a Silverlight application that’s actually a migration of an ASP.NET application. To cut costs, you must perform this migration in several parts. Instead of requiring that all the functionality is converted to Silverlight in one go, you can opt to leave some part in ASP.NET for the time being and still integrate it in the Silverlight environment.

As said, the control available for this, is the WebBrowser control.  The following properties are the most important ones when working with the WebBrowser control: 

· Source: gets or sets the URI that should be rendered in the WebBrowser control

· Navigate: specifies the URI that should be loaded in the control (works identical to the Source property)

· NavigateToString: you can also display an on-the-fly generated string of HTML. This can be done using this method.

The WebBrowser control only works when the Silverlight application is running out-of-browser. If we try running it in-browser, we’ll see a rectangle saying that the HTML is disabled.

image

If we’re running this sample out-of-browser and navigate to this very site (www.snowball.be), we’ll see the following:

image

Let’s now take a look at some code to create this.

The following is the declaration of the WebBrowser control itself:

<WebBrowser x:Name="MainWebBrowser" 
            Width="800" Height="600"></WebBrowser>

In the code-behind, in the click event of the Go-Button at the top, we can send the WebBrowser control to the requested page:

private void AddressButton_Click(object sender, RoutedEventArgs e)
{
    if (Application.Current.HasElevatedPermissions)
        MainWebBrowser.Navigate(new Uri(AddressTextBox.Text));
    else
    {
        string localIFrame = 
                "<HTML><HEAD></HEAD><BODY><IFRAME width='100%'      
                height='100%' src='" + AddressTextBox.Text + "' /></BODY></HTML>";
                MainWebBrowser.NavigateToString(localIFrame);
    }
}

As you can see, there are 2 implementations of the navigation. Why is that? When running out-of-browser, the WebBrowser control works, BUT it can only navigate to pages within the same domain as where the Silverlight application is hosted. To navigate to an external page (that is on another domain), the Silverlight application needs elevated permissions: it must be a Trusted Application. ( We’ll look at Trusted applications in a future post). This is reflected by the first check.

Now there’s a little workaround this limitation and that’s adding an IFRAME control manually and hosting the external page in there. This is done in the else-block.

Note: this is a Silverlight 4 feature which only works in Visual Studio 2010!

The sample can be found here.

  Posted on: Thursday, December 03, 2009 12:46:46 AM (Romance Standard Time, UTC+01:00)   |   Comments [1]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 1, 2009    

Question: how many times a day do you move things around in your PC environment? Placing a file on your desktop, picking it up and moving or dragging it into a folder is something we all know and do constantly. Also, personally, I often drag a file into a window to trigger the application to do something with it. Often when I’m doing some quick editing, I drag an image onto Photoshop’s desktop icon. Or when I want to send a mail with an attachment, I drag the file into the window. The application gets a handle to the file and knows what to do with it.

Silverlight applications could not be the target of a drag and drop operation. It was possible to drag stuff around inside the Silverlight window, but it was not possible to drag things into the window running Silverlight. Things changed in this area with the arrival of Silverlight 4. At the time of writing, it’s only possible to drag in one file or a list of files, however dragging in a directory is not supported. This feature is available on Windows and Mac.

Any UIElement within Silverlight can now be the target of a drag operation. IThe UIElement class now defines several events to support dragging, namely DragEnter, DragLeave, DragOver and Drop. DragEnter, DragLeave and DragOver can be used for example to highlight a control when content is being dragged over it. The Drop event fires when an object is dropped onto the UIElement. Let’s take a look at a sample.

Imagine we are building an application in which the user can drag and drop images on a canvas. The way the Canvas needs to be declared is as follows:

<Canvas x:Name="DropCanvas" AllowDrop="True" Drop="DropCanvas_Drop" >

In code-behind, we should handle the Drop event to react to a file being dropped on the UIElement.

private void DropCanvas_Drop(object sender, DragEventArgs e)
{
    IDataObject dataObject = e.Data;
    Point dropPoint = e.GetPosition(DropCanvas);
    if (dataObject.GetDataPresent(DataFormats.FileDrop))
    {
        FileInfo[] files = (FileInfo[])dataObject.GetData(DataFormats.FileDrop);
        
        if (files.Length > 0)
        {
            if (files[0].Extension == ".jpg")
            {
                //only take file 0
                System.Windows.Media.Imaging.BitmapImage bitmapImage = 
                    new System.Windows.Media.Imaging.BitmapImage();
                bitmapImage.SetSource(files[0].OpenRead());
                Image newImage = new Image();
                newImage.Source = bitmapImage;
                newImage.Width = 200;
                newImage.Height = 200;
 
                newImage.SetValue(Canvas.TopProperty, dropPoint.Y);
                newImage.SetValue(Canvas.LeftProperty, dropPoint.X);
 
                newImage.Stretch = Stretch.Uniform;
                DropCanvas.Children.Add(newImage);
            }
        }
    }
}

This event defines a DragEventArgs parameter, which defines a Data property, of type IDataObject. We can access the file or files using the GetData method. This method returns an array of FileInfo objects and these files can then be read out. The code for this is shown below.

We check if the file is an image (check for the file extension) and if it is, we create a new BitmapImage, passing in the dropped file. After that, we create a new Image control and set its source to the BitmapImage instance.

Note: this is a Silverlight 4 feature and the sample only works with Visual Studio 2010!

The complete code can be downloaded here: DragAndDrop.zip (29.78 KB)

  Posted on: Wednesday, December 02, 2009 12:42:41 AM (Romance Standard Time, UTC+01:00)   |   Comments [2]
         
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     November 30, 2009    
Here’s the first article of the Silverlight Advent Calendar! We are starting quite easy…
 
While browsing through the new properties and types available in Silverlight, I came across this nice little new property on the TextBlock called TextTrimming. As the word says, it helps you with showing an ellipsis when the text is too wide for the TextBlock you want it to appear in.

Let’s take a look at this property in action. Suppose we have a TextBlock that has a specific width set to it. On this TextBlock, we specify the TextTrimming property to have the value WordEllipsis.

   1: <TextBlock Text="Hello, my name is Gill Cleeren" 
   2: Width="150" TextTrimming="WordEllipsis"></TextBlock>

Without the TextTrimming property, the result is the following. As you can see, the text is cut of where the TextBlock ends.

image

However, with TextTrimming enabled, Silverlight calculates where it should be placing the ellipsis, making the result look much more polished.

image

Note that is a Silverlight 4 only feature, which only works with Visual Studio 2010!

Tomorrow, we’ll be looking at… Oh can’t say, that has to be a surprise until tomorrow! You can’t go peeking in that advent calendar!

  Posted on: Tuesday, December 01, 2009 12:02:45 AM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     Silverlight | sl4 | Silverlight Advent Calendar     November 30, 2009    

December is a month of festivities, presents and great food. With Christmas just around the corner, the year has been flying by even faster than the previous one.

To go out with a bang (or should I have said bing…), I have decided to come up with something special called “the Silverlight Advent Calendar”. As probably, many of you don’t know what an advent calendar is as it is something only known in some cultures, let’s start with a little explanation I found on Wikipedia:

An Advent calendar is a special calendar which is used to count or celebrate the days of Advent in anticipation of Christmas. Some calendars are strictly religious, whereas others are secular in content.

Today, most advent calendars are made for children. Many take the form of a large rectangular card with many "windows", one of which is opened every day during Advent. In less elaborate calendars, each window opens to reveal an image, a poem, or part of a story such as the Nativity story itself. More elaborate Advent calendars have a small gift concealed in each window, such as a toy or a chocolate item.

Here are some examples:

advent-calendar

2007-11-26-advent

However, in my calendar, there’s no chocolate for every day you open it! I have something much better… Each day, starting December 1st, I will be posting a Silverlight article here on www.snowball.be. That’s right, a free article on Silverlight for every day you stop by! You don’t even have to open a little door or something to get a free gift!

Christmas must be early this year!

Disclaimer: I HOPE to be able to post each day, as December is a very busy month for me…

  Posted on: Monday, November 30, 2009 11:18:21 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Gill Cleeren     Efficiency | PDC | Silverlight | sl4     November 18, 2009    

Remember my post on printing in Silverlight 3, using the WriteableBitmap. This class allowed to export UI elements to an image and print from there. While it was working, it wasn’t a great way of doing things.

Silverlight 4 brings real printing to the table. All printing is done using the PrintDocument class. In it’s PrintPage event, we can specify what content needs to be printed. This can be the entire screen, a control that’s part of the visual tree or even a control that’s generated on the fly. Finally, we use the Print() method to perform the actual printing of the document.

Let’s take a look at some really easy code to do all this.

The UI code is kept simple intentionally:

    <Grid x:Name="LayoutRoot" Background="White">
        <TextBlock Height="25" HorizontalAlignment="Left" Margin="62,92,0,0" Name="textBlock1" Text="I want to print!" VerticalAlignment="Top" Width="194" FontWeight="Bold" FontSize="15" />
        <Button Content="Print" Height="55" HorizontalAlignment="Left" Margin="62,213,0,0" Name="PrintButton" VerticalAlignment="Top" Width="216" Click="PrintButton_Click" />
    </Grid>

This looks like the following:

image

In the click event of the button, we write some printing code.

 

        private void PrintButton_Click(object sender, RoutedEventArgs e)
        {
            PrintDocument document = new PrintDocument();
            document.PrintPage += (s, args) =>
                {
                    args.PageVisual = LayoutRoot;
                };

            document.Print();
        }

This will now show a print preferences dialog, in which we can select a printer. The result in this case is the entire UI being printed, because LayoutRoot was specified.

We can also hook into the beginning and ending of the printing process using the StartPrint and EndPrint event. These can be used to execute some code at the start or ending of the printing process.

  Posted on: Thursday, November 19, 2009 12:38:20 AM (Romance Standard Time, UTC+01:00)   |   Comments [3]
         
Gill Cleeren     Efficiency | Silverlight | sl4     November 18, 2009    

Today at the PDC09, Microsoft announced Silverlight 4, the 4th version of the RIA platform.

You can get the bits here:

  • Visual Studio 2010 Beta 2 or Visual Web Developer Express 2010 Beta 2 (pick one)
  • Silverlight Tools for Visual Studio 2010
  • Expression Blend for .NET 4 Preview – for authoring Silverlight 4 and WPF 4 applications
  • WCF RIA Services (formerly .NET RIA Services) (NOTE: This is actually included in the SL Tools for Silverlight 4)
  • Silverlight 4 SDK CHM (offline documentation) – optionally online here as well
  • Updated Silverlight Toolkit for Silverlight 4
  • Developer runtimes: Windows and Mac platforms
  • Silverlight 4 SDK only – not needed if you install the tools above
  • Silverlight Media Framework – a new, Open Source media player framework for you to use.
  • (This list was shamelessly copied from Tim Heuer’s blog post on Silverlight 4)

      Posted on: Wednesday, November 18, 2009 7:30:30 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
             
    2/4/2012   3:56:51 PM
     Welcome to Snowball.be
    Hello and welcome to snowball.be!

    My name is Gill Cleeren, I'm a Microsoft Regional Director and an MVP ASP.NET.
    On Snowball.be, you'll find all kind news and articles on .net, ASP.NET, WPF, Silverlight and Microsoft in general.
    More on me can be found on my about page.

    Should you have any questions, don't hesitate to contact me by Send mail to the author(s) .

     Partner sites
     Most popular tags
    .net (124) .net 3.0 (6) .net 3.5 (18) .NET 4 (18) .NET Show (1) ADO.net (4) ASP.net (53) ASP.net AJAX (4) ASP.NET MVC (3) Atlas (12) Azure (2) Blend (2) Book (5) Book review (4) C# (43) Case studies (1) Chopsticks (3) Community (10) Community Day (15) Consoles (1) Database (1) DevDays09 (4) DotNetNuke (4) Efficiency (57) Enterprise Library (5) Events (60) Expression (7) Games (3) Hardware (9) Internet (18) IT (1) jQuery (1) LightSwitch (3) Links (11) LINQ (4) Mac (2) Metro (1) Microsoft (75) Mix 07 (6) Mix 08 (4) Mix 09 (1) Mix 11 (1) Movies (4) MVP (5) MVP Summit 2008 (3) mvvm (1) Office 2007 (10) Other (8) PDC (22) PDC2008 (10) Personal (36) ppt (9) Programming (52) Programming tools (22) Regional Director (2) Silverlight (142) Silverlight Advent Calendar (24) sl4 (44) Slide decks (13) Snowball (13) Software (20) Microsoft (25) Speaking (14) SQL Server (10) TechDays (13) TechEd (14) telerik (6) Telerik (6) TFS (1) Twitter (1) Vista (73) Vista Tricks (9) Visual Studio.net (38) Visug (33) VS2010 (8) Wallpaper (2) WCF (2) Webcasts (9) Webinars (5) Windows (41) Windows 7 (5) Windows 8 (1) Windows Azure (2) Windows Mobile (3) Windows Phone 7 (2) WinFX (17) WinRT (1) WP7 (2) WPF (40) XAML (24)

     On this page
    Part 1 of Silverlight exam preparation online
    Working with the RaiseCanExecuteChanged in MVVM Light (Silverlight)
    The INavigationContentLoader interface in Silverlight 4
    Slides and demos for SilverlightShow webinar
    Slides and demos for Silverlight Show webinar
    Silverlight Firestarter on December 2nd
    Upcoming webinar: 10 tips in Silverlight
    Announcing: Silverlight Tour is coming to European countries now!
    Telerik Silverlight Sweden roadshow was a success!
    ReMix 2010 demo and slide deck
    Silverlight Roadshow in Sweden coming up
    Building an app marketplace with MEF (MEF/Silverlight 4 tutorial)
    More praise for my Silverlight 4 book
    The jury has spoken: some reviews of my book
    My book released: Silverlight 4 Data and Services Cookbook
    Developers cheering all over the world: Visual Studio 2010 is here!
    TechDays 2010: My sessions slides and demos
    Busy times… but my first book is almost here!
    Silverlight Advent Calendar: December 24th: Browsing Christmas pictures on Flickr
    Silverlight Advent Calendar: December 23rd: Merged resource dictionaries
    Silverlight Advent Calendar: December 22nd: INotifyDataErrorInfo in the spotlight
    Silverlight Advent Calendar: December 21st: Duplex WCF bindings in Silverlight
    Silverlight Advent Calendar: December 20th: Learning about the IsolatedStorage
    Silverlight Advent Calendar: December 19th: Entering credentials via ClientHttp
    Silverlight Advent Calendar: December 18th: IDataErrorInfo in an example to stop Last Christmas by Wham!
    Silverlight Advent Calendar: December 17th: Cross-domain network access
    Silverlight Advent Calendar: December 16th: The new DataGrid has landed!
    Silverlight Advent Calendar: December 15th: Right-clicking in Silverlight 4 to create a context menu
    Silverlight Advent Calendar: December 14th: The Local Connection API explained
    Silverlight Advent Calendar: now taking requests
    Silverlight Advent Calendar: December 13th: Working with Bing from Silverlight
    Silverlight Advent Calendar: December 12th: The RichTextArea exposed
    Silverlight Advent Calendar: December 11th: Local file access in Silverlight 4
    Silverlight Advent Calendar: December 10th: Working with the webcam from Silverlight 4
    Silverlight Advent Calendar: December 9th: Element-to-element bindings in Silverlight 3
    Silverlight Advent Calendar: December 8th: Working with the clipboard in Silverlight 4
    Silverlight Advent Calendar: December 7th: Creating a kiosk application
    Silverlight Advent Calendar: December 4th: Replacing converters with new data binding features
    Silverlight Advent Calendar: December 3rd: The new Silverlight 4 WebBrowser control
    Silverlight Advent Calendar: December 2nd: Drag and drop in Silverlight 4
    Silverlight Advent Calendar: December 1st: Text trimming made easy in Silverlight 4
    Silverlight Advent Calendar coming up!
    Exploring Silverlight 4: Printing in Silverlight 4
    Silverlight 4 is here!
     This site
     Archives
    Navigation
     Sitemap
     Blogroll OPML
     Disclaimer

    All content is property of www.snowball.be. Nothing on this site can be copied or published elsewhere, unless otherwise stated.

    This site is made by Gill Cleeren.

    Questions? Opinions? Send mail to the author(s) E-mail