2 years and 266 posts later...

2 years ago, on a Sunday, I posted my first blog post. Since then so many amazing things happened, partly due to this blog: I got the MVP status, I got a better recognition in my firm for my expert knowledge on some topics (such as WPF, Silverlight, ASP.NET and C#), I started speaking in conferences... One year later, I got a book deal (more on this soon). I met amazing people, and made a lot of new friends in the industry. I went to Redmond a few times and had the chance to talk to some really amazing talents in the software field. More importantly, I really had the feeling that my contributions were acknowledged, and valued. It's really been 2 amazing years.

To all of you reading these lines, thank you. You make my life as a software engineer better, more interesting, and you really help become a better developer.

Thank you

Silverlight 2 beta 2 is live!

Here we go, Silverlight 2 beta 2 can be downloaded and installed! I had the chance to take part to an "insiders" program at Microsoft, and to play with SL2 b2 for a couple of weeks, and it's a good one. You should switch to b2 as soon as you can!

There are obviously incompatibilities between b1 and b2, but much, much less than between the alpha version and b1. We're getting there!!

Silverlight 2 beta 2 will be used to build applications related to the Beijing olympics, so it's going to be a real nature test for that version. As for the final release.... it's still very much hush hush, so let's leave it for now :)

The best place to start is ScottGu's blog. As usual, Scott describes the new features at length, and has links to all the places where you can download the good stuff.

Note that there is also a new version of Blend 2.5 which can be installed next to a "normal" Expression Blend V2. There is supposed to be a new version of Deep Zoom Composer too, but the download seems to be down currently.

Enjoy!!

Microsoft, you're kidding me, right??

You got to be kidding me. What if I want Expression in the US locale, I can't buy it just because my IP is not in the US? Honestly? You are *that* stupid?

WTF

A short break

I am going to take a short break of blogging for a couple of months. The reason is simple: I have been working on a book about Silverlight 2 since September last year, and we are in a phase now where I need to concentrate on that exclusively, and put other activities aside. I might post the occasional article from time to time, but until mid-Summer, it's going to be write write write.

Stay posted for news about the book coming up, and don't delete me from your feeds, it's really only temporary :)

My talk at the "Internet Briefing RIA conference" in Zurich

I just posted today's talk at the RIA conference in the World Trade Center, Zurich. Unfortunately it was not recorded, but the slides and the demos' source code is available on my site.

The talk went really good, even though the crowd was rather tough :) Trying to "sell" Windows Presentation Foundation, a desktop Windows-only technology, to an audience of web developers, many of them using Java and open source technologies (and even one Adobe employee) sparkled some very interesting discussions. I can't say I convinced everyone (and it was most certainly not my intention), but I think everybody had a really good time. I know for sure that I did!

To all those who stayed until the end of my presentation, and even though mine was the last presentation of the day, thank you very much!! To those who couldn't stay, I hope you'll have fun checking the slides and the demos, and contact me if anything is unclear!!

TweetMyPage V0.2 - Now with "from TweetMyPage" indicator

As soon as I had my info page online, I asked Twitter to accept TweetMyPage as a Twitter application, and to mark the messages posted with TweetMyPage with "from TweetMyPage". Note for developers: There is a form to fill on the Twitter API page. It's really fast, and one day later I got the answer that it was accepted.

From now on, messages posted from TweetMyPage are marked as such:

posted from TweetMyPage

I got a couple of testers so far, and already got a few requests for additional features. I am now evaluating how I can modify the application to integrate these new features, and will update TweetMyPage as soon as I got time (in 2018) (just kidding).

TweetMyPage is in beta for the moment, and if you want to try it, I'll be happy to send you an invite (just leave a comment down here or send me an email. If all goes well, I will make TweetMyPage public next week or so.

GalaSoft "TweetMyPage" released for tests

GalaSoft "TweetMyPage" is a web application allowing you to post to Twitter what you're currently reading in your web browser, on a simple button click.

After you install the small "scriptlet" button in your web browser's "bookmarks toolbar" (Firefox) or "Links toolbar" (IE), any time you want to share what you're reading with the world, you can simply click on the "TweetMyPage" button.

TweetMyPage button

If it's the first time in this session that you are posting, you will be asked to enter your Twitter user name and password. After that first time, you will not be asked for it anymore, not until you close your web browser.

As a result, a message will be sent in your name to Twitter, for example:

Twitter entry

When you create the "Bookmark button" in the Settings page, you can customize the "Reading" prefix that will be posted, as well as a couple of other settings.

TweetMyPage is in beta for the moment, and if you want to try it, I'll be happy to send you an invite (just leave a comment down here or send me an email. If all goes well, I will make TweetMyPage public next week or so.

WPF talk this Thursday: "Ultra Rich Interactive Applications"

I have been in very much stress lately and hardly had time to post, but I don't forget you, dear readers...

Anyway, this Thursday, I will be talking in a RIA conference organized by the Internet Briefing group here in Zurich, in the World Trade Center. My talk is titled "Ultra Rich Interactive Applications with WPF" and subtitled "When Silverlight is not enough...". I think it's going to be an interesting talk (but obviously I am partial) about the major differences between WPF and Silverlight, and the added richness that WPF provides. I am a big fan of Silverlight, but I have to admit that it's nice going back to the amazing power of WPF sometimes, without having to worry about "is that feature even implemented in Silverlight"?

The talk takes place between 16:30 and 17:30 in the World Trade Center, Leutschenbachstrasse 95, 8050 Zürich. Hoping to see some of you there, maybe!

New GalaSoft stickers

On a whim, I made a GalaSoft sticker and ordered 48 of them at CafePress.com. The stickers just arrived yesterday, and they look pretty cool. I plan to keep some on me, so next time you cross my path, make sure you get a GalaSoft sticker for your laptop

GalaSoft sticker
My laptop

http://www.galasoft.ch

My resume is now online

I finally did something I wanted to do for a loooooong time: I cleaned up and put my resume online on my website. Note for Beat (my boss), if you read this, don't panic, I am not leaving just right now :) Anyway. For those of you who like to know my (professional) self better, feel free to take a look. If you want a username and password to check my certificates and awards, contact me. And if you have any comment, give me feedback!!

http://www.galasoft.ch

WPF: ListView/GridView minimum and maximum width for a column

A WPF ListView is a possible replacement for a datagrid, when it doesn't have to support advanced features like grouping or filtering of rows. If you use a ListView in your WPF application, and set the "View" property of this ListView to be a GridView.

A ListView/GridView even supports features like reordering and resizing columns. Unfortunately, it is not possible to define a minimum or maximum width for the columns. Fortunately, it is not really to do this in the code behind. Let's see how.

First we need to understand how exactly the resizing of a GridView column works. When a column can be resized, a narrow vertical line appears on the right side of the column. Passing the mouse over this line turns the cursor into a "resize" cursor.

To find out what exactly this line is made of, we can use a tool like Snoop, or Mole. These tools display the inner structure of a WPF UI, also known as the Visual Tree. For example, in Mole, we can navigate down to our ListView and display the header row's inner structure:

Header row of a ListView

The feature that is of particular interest to us is the "Thumb" control, named PART_HeaderGripper. This requires some explanations:

  • A Drag action is the action through which a control is selected (click-and-hold) and then the mouse is moved. The expected action is usually that the clicked control moves together with the mouse, but other actions may be performed too, for example resizing the columns of a grid, etc...
  • A Thumb is a small WPF control that can be dragged. It has a collection of events that are used to program what happens when a drag action is performed on the control. For example, the event Thumb.DragDeltaEvent is fired every time that the Thumb is dragged a little.
    Note: A Thumb doesn't really look like anything (well, it does look like a Rectangle!). With the great ability that WPF has to redefine the look&feel of any control, you can make a Thumb look like anything you need. This is why the Thumb control is in the namespace System.Windows.Controls.Primitives: The Thumb is usually used to create other controls, hence the "Primitives".
  • The makers of WPF controls have for convention to name inner controls of other controls with the "PART_" prefix.

Once we know this, we can try to intercept the events raised by the Thumb control named "PART_HeaderGripper", when the ListView's user resizes the columns. Remember, in WPF, events are "routed", we say that they "bubble" up from the control they originate from to the parent and the parent's parent, etc...

As a first try, we can add an event handler on the ListView and try to handle the "Thumb.DragDelta" event:

<ListView x:Name="MyListView" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=Items, Mode=Default, Source={StaticResource DataProvider}}" Thumb.DragDelta="Thumb_DragDelta">

with:

void Thumb_DragDelta(object sender, DragDeltaEventArgs e) { // Do nothing for the moment Console.WriteLine("Thumb_DragDelta"); }

Unfortunately, if we place a breakpoint inside the Thumb_DragDelta event handler, it is never reached, not even if you resize any column of the ListView. Why not? Well, when a routed event is handled by any control, it can be marked as "handled". This is done by setting the RoutedEventArgs.Handled property to true inside the event handler.

Fortunately, there is a way to tell the framework that we are interested in an event even if it has been marked as handled. We cannot do this in XAML, however, so just remove the Thumb.DragDelta from the XAML:

<ListView x:Name="MyListView" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=Items, Mode=Default, Source={StaticResource DataProvider}}">

Instead, we will add an event handler in code behind. This is one of the few things that you cannot do in XAML!

public Window1() { InitializeComponent(); MyListView.AddHandler(Thumb.DragDeltaEvent, new DragDeltaEventHandler(Thumb_DragDelta), true); }

Notice that the last parameter of the AddHandler override is set to "true": This is what indicates that we want to get notified when the DragDelta event "bubbles" to us, even if it has been marked handled before it reaches us. This time, if you run the application and resize a column, the event handler is executed and the breakpoint is reached.

The last thing we need to do is to forbid the column to be resized under a minimum size, or above a maximum size. To do this, we need to do a few steps:

  • Get the Thumb at the origin of the event. This is not the "sender" parameter, because the event handler is placed on the ListView. So even though the routed event originates on the Thumb, the "sender" is actually the ListView. However, there is another way to get the Thumb: The parameter "e" (of type DragDeltaEventArgs), like all RoutedEventArgs, contains a property named "OriginalSource". This is the Thumb we want!
  • Then, we want to get the GridViewColumnHeader containing the Thumb. Here too, we need to understand how the visual tree is built. All controls in WPF are essentially lookless, and the look&feel is created in a ControlTemplate, which is separate. We can, however, get the parent's template using the TemplatedParent property.
  • We're almost there: Once we have the GridViewColumnHeader, all we need to do is get the Column it belongs to (conveniently exposed in the Column property), and set its Width to the minimum respectively maximum value we want to use. Translated in code, this is:
void Thumb_DragDelta(object sender, DragDeltaEventArgs e) { Thumb senderAsThumb = e.OriginalSource as Thumb; GridViewColumnHeader header = senderAsThumb.TemplatedParent as GridViewColumnHeader; if (header.Column.ActualWidth < MIN_WIDTH) { header.Column.Width = MIN_WIDTH; } if (header.Column.ActualWidth > MAX_WIDTH) { header.Column.Width = MAX_WIDTH; } }

where MIN_WIDTH and MAX_WIDTH are two constants. We could as well use properties to be able to set these values from the outside.

With this code, the column will be resizable up to a certain limit, and then the Thumb will stop moving. While it requires a good understanding of the inner works of a WPF control, this is not very complicated. It requires some code-behind, however, and cannot be done in pure XAML.

http://www.galasoft.ch

More US centric discrimination: Amazon.com MP3 download

This kind of things pisses me up so much. What's your problem Amazon? My money is not good enough for you? I call it discrimination.

Oh yeah, also something else. Could you tell me that *before* you make me install your downloader? Kthxbai.

US centric discrimination

http://www.galasoft.ch

Silverlight: User Controls with events

This article is for Silverlight 2 beta 1

Update: Corrado Cavalli translated the example in VB.NET. Thanks Corrado!!

Apparently, one reader had issues declaring events for the User Control example that I posted earlier this week.

He is programming in VB and unfortunately I don't have a lot of experience with VB.NET, so I first created a working example with C#, and my good friend and fellow MVP Corrado Cavalli translated the example in VB.NET (see below).

The big difference between WPF and Silverlight regarding events is that Silverlight doesn't support Routed Events (yet?). To be precise, some events are routed (all input events like MouseLeftButtonDown, KeyDown, etc...

Instead of declaring RoutedEvents in our User Control, we have to resort to standard .NET events then. From a user point of view, it doesn't make a very big difference in the subscribing, but of course these events will not tunnel nor bubble (for a summary of RoutedEvents, bubbling and tunneling in WPF, read this).

The sample here declares a User Control called LeftRightButton, with two buttons, a LeftButton and a RightButton. it also declares two events, a LeftClick and a RightClick. When the RightButton gets clicked, the UserControls catch this event and raises a RightClick event. The same happens with the LeftButton and the LeftClick event.

Declaring new events for any class requires a Handler declaration (a delegate), and then the event declaration itself.

public delegate void ClickHandler(object sender, EventArgs e); public event ClickHandler RightClick; public event ClickHandler LeftClick;

The next step is to catch the internal click events, and to raise the corresponding "external" event. Note that in this simplified example, I just re-route the RoutedEventArg for the event. Often, you need to declare your own class inheriting EventArgs, for example to pass additional parameters to the event subscriber.

So if the XAML LeftButton is declared as:

<Button x:Name="LeftButton" Click="LeftButton_Click" />

then we have:

void RaiseLeftClick(RoutedEventArgs e) { if (LeftClick != null) { LeftClick(this, e); } }

Note how we check if the event is null before we raise it. If no one subscribed to the event, LeftClick will be null, and there is a risk for a NullReferenceException to be thrown.

Then only thing that we need to do now is catch the internal click event, and raise the corresponding RightClick or LeftClick event.

private void LeftButton_Click(object sender, RoutedEventArgs e) { RaiseLeftClick(e); }

The User Control raising these events is located in an external assembly as shown here. I use 4 instances of the User Control in a Silverlight application. This way, we demonstrate how to raise new events, how to catch them in another assembly, and how to handle them.

<controls:LeftRightButton x:Name="ButtonTopLeft" RightClick="LeftRightButtonButton_RightClick" LeftClick="LeftRightButtonButton_LeftClick" />
private void LeftRightButtonButton_LeftClick(object sender, EventArgs e) { LastEventControlNameTextBlock.Text = (sender as LeftRightButton).Name; LastEventEventNameTextBlock.Text = "LeftClick"; }
4 user controls with events

The source code in C# can be downloaded here.

The source code in VB.NET (translated by Corrado Cavalli) can be downloaded here.

http://www.galasoft.ch

Silverlight: Running standalone full trust applications

Introduction

I guess that it's time to write about it, after making a few people curious at the MVP summit in Seattle. This article is to be taken as a proof of concept, and (I hope) as a way to "motivate" Microsoft to integrate this ability into Silverlight.

As soon as I started playing with Silverlight, I saw the great potential that this technology has. As a RIA technology, it provides extended functionality over the web. As a WPF subset, it allows me to leverage the knowledge I already acquired in the past, and to reuse it for web applications. This in itself makes Silverlight a technology I *have to* learn.

But what if... what if we could use Silverlight to run lightweight .NET applications in standalone mode? A little like Adobe AIR is offering, but with the power of .NET instead of ActionScript. Imagine a small application, running on a small framework, installed in typically 10 seconds.

I posted an article on my site explaining the thought process and giving information about standalone Silverlight applications, their promises and their limitations. For those of you too impatient to read the full article :) you can download a demo and the source code directly from here.

The demo

To install the demo, follow the steps:

  • Download the Zip file.
  • Extract the Zip file to a folder on your hard drive.
  • On Windows: double-click the file "Start.hta".

This starts the MSHTA host, and displays the Silverlight application.

Silverlight application in MSHTA
Silverlight application in MSHTA
  • Enter a directory path in the first textbox, and then click on "Get list of files". This displays the corresponding list in the listbox.
  • Select a file. Its name is displayed in the second textbox.
  • You can now modify the file name and press on "Rename".
  • Enter any file path in the last textbox and press "Does file exist?". A corresponding message is displayed in the status bar.

This last functionality is also available in Mozilla-based browsers, for example Firefox. You can try it by setting Firefox to be your default browser, and then double-clicking the file "index.html" located in the same folder as "index.hta". This starts the application in "file" mode, and you get the same permissions. The other functionalities "Get list of files" and "Rename" are not implemented in Firefox and will raise an error.

Silverlight application in Firefox
Silverlight application in Firefox
Source code

As usual, the source code is available for download. It contains the following projects:

  • GalaSoft.SL.TestHta: This is the Silverlight application you want to run. It contains an "index.html" file, which should be the start page if you run the application in "F5" or "Ctrl-F5" mode in Studio. Visual Studio runs the HTML file in file mode, so you get a chance to debug the Silverlight code, but unfortunately it is not possible to debug the JavaScript code. When you build the project, a "index.hta" file is automatically created. This is exactly the same as "index.html", but with a different extension. Double-clicking this file in Windows Explorer will start the MSHTA host.
  • GalaSoft.SL.IO: This is a library defining a new DirectoryInfo and FileInfo classes. These classes mimic the actual System.IO.DirectoryInfo and System.IO.FileInfo classes. They use the class "GalaSoft.SL.IO.ScriptFacade" to channel the full-trust calls to the script code contained in the file "script\gslb.filesystemexplorer.js".
  • GalaSoft.SL.IO.Test: A Unit Test application for GalaSoft.SL.IO. Written using the Silverlight Unit Test framework and accessing JavaScript as described here. I use this to unit test all my IO classes and methods, including the corresponding JavaScript file.
    Note: The console application "GalaSoft.SL.IO.Test.Prepare" must be executed before the unit test is run.
  • GalaSoft.SL.IO.Test.Prepare: This console application is needed to create a few directories and files in the local drive in order to unit test the library GalaSoft.SL.IO. It requires write-permission to the folder c:\temp. Unfortunately, I don't think that Mock frameworks exist for JavaScript yet.

In normal use, the project GalaSoft.SL.TestHta should be chosen as startup project, and its file "index.html" as startup page. You can modify the application code. If you change the HTML code, the changes will automatically be copied to "index.hta" when you build the application.

Components involved in a standalone Silverlight application
Components involved in a standalone Silverlight application

http://www.galasoft.ch

I am now a Microsoft Certified Professional

What a crazy week that is. I am currently in Seattle for the Microsoft Most Valuable Professional summit, which ended yesterday. I took an additional day in Seattle to meet a few friends and Siemens colleagues, and this morning got an email notifying me that I passed the MCTS exam about WPF that I took back then in December.

Because the exam was in beta stage when I took it, Microsoft needed a veeeeeeeery long time to evaluate the replies and check if I met the requirement. Apparently, they also had issues finding volunteers to try the beta exam, so it took even longer than planned. But hey, everything happens when you wait long enough, and as of today I am a Microsoft Certified Professional.

Now I want to point again what I wrote in December: I am not quite sure about the value of the MCTS exams. You are not a good developer just because you learn answers by heart. Testing one's knowledge with multiple choice questions is really absurd, especially when it comes to programming. Additionally, in Europe, most firms I know of really don't care if you have a cert or not, and rather look to your credentials, experience and education, as well as things like involvement in the community, etc...

But hey, the exam was free, it was fun learning for it, and I got the title, so what am I complaining about? :)

http://www.galasoft.ch