Donnerstag, 27. Oktober 2011

The Silverlight ListBox and the space bar

I have, as I think, a quite common scenario: I have a ListBox control containing items that have a checkbox. I want to enable the user to remove items using the delete key and to toggle the checkbox using the spacebar.

So I set up a little MVVM magic to bind the keydown event of the listbox to my view model. Everything is working fine for the delete key. But when it comes to space, I never reached my command handler. It could not be an issue with the command binding, because it worked for delete.

So I searched around and found out that I was not the only one having recognized the issue. The post I found was from 2009 and written about Silverlight 2. I am wondering why this behaviour has not been changed because it seems hardly reasonable to me.

The technical reason for this behavior is, that within the ListBox control in the OnKeyDown method, if the pressed key is space, the Handled flag of the event parameters is set to true, so the space bar press will not propagate upwards the visual tree.

The solution is easy: inherit your custom ListBox control, overwrite the OnKeyDown method, handle the space press and set Handled to false:


protected override void OnKeyDown(KeyEventArgs e)
{
     switch (e.Key)
     { 
           case Key.Space:
                 e.Handled = false;
                 break;

           default:
                 base.OnKeyDown(e);
                 break;
     }
}

Lucky you, if you already have your custom control project in place...

Dienstag, 18. Oktober 2011

CQRS - Commands and Queries are different

It is always nice to have a practical break-through in gaining a deeper understanding of a certain pattern. I experienced this a few days ago with the CQRS pattern.

What is CQRS?
For those who have not yet heared abaout CQRS start your reading with this blog. I will try to summarize it in a few words: the acronym is for Command and Query Responsibility Segregation. On a method level it simply means to have methods that either return a value (Query) or that do something (Commands):

Instead of:
public double Add(double x, double y)

Write:
public void Add(double x, double y)
public double GetResult()

This "Method Level CQRS" is called CQS (Command Query Separation) and was devised by Betrand Meyer.

CQRS takes this idea and leverages it to the application architecture level. It promotes the idea that commands and queries are two completely different things that need to be treated differently. A common argument for this is scaling: due to the fact that queries are far more frequent than commands, you should be able to let ten servers run queries while one server for executing commands will suffice.

I am not Google - what do I care?
Besides the fact that CQRS enables you to do other nice things like event sourcing, and that it fits nicely with Domain Driven Design you may ask yourself why you should care about scaling if your application will never reach such a massive scale.

Here comes the personal break-through I had: you should care, because commands and queries are simply different! Here is my example: Consider a service based environment. It was decided that every service operation will always deliver its result by means of an object called OperationResult<T>:

public class OperationResult<T>
{
  public T Result { get; set; }
  public Message Message { get; set; }
  public bool Succeeded { get; set; }
}

The Message class simply holds some describing text, a message number and a list of Message objects.

Problems arised with the Succeeded-flag and how to construe it. I one thing we all agreed: if an exception occurs, the flag must be false. But what if a Method like "ChangeOrderState" does not succeed due to validation errors or any other business logic? Then the operation is failed as well. But what if you have a method like "GetCustomerById" - if there is no customer with a given id, the Result will be null. But this is a valid result. But isn't the method failed because it was the users intention to find something? But in the client we want to check succeeded and if it is false, we assume that something did not went well and we dont want to check for the Result to be null in this case.

The crux in the above example arises from the different nature of a method called "ChangeOrderState" and "GetCustomerById". The former is a command while the latter is a query. And besides technical failures, a query can not fail - but a command can. The way of interpreting the succeeded flag depends upon the kind of method called.

Commands and queries are different
I very much enjoyed having this insight, because it showed that CQS and CQRS are relevant to every developer, regardless of the size of your project. You should be aware of the fact that queries and commands are different and you should perhaps treat them differently.
For example in having a QueryResult<T> and an CommandResult<T>. Or, even better in the sense of CQRS, have a QueryResult<T> and a CommandResult, where the latter does not deliver a Result but only the Succeeded flag and a Message.


Freitag, 23. September 2011

SQLite, Visual C++ and migration from .NET 3.5 to .NET 4.0

Recently we migrated our .NET 3.5 based projects to .NET 4.0. With a little self written tool that changes the framework version in the .csproj files (there are a lot of them) and a little maual work the job was quickly done. But then came the testing of the setup made up of the new files. This was were the tragedy began.

New Version of System.Data.SQLite for .NET 4.0
We had problems with the System.Data.SQLite.dll we were using. We found out that you need a new version of the dlls for .NET 4.0 (can be downloaded from the vendors page). That was the easy one.

32 bit or 64 bit
The .NET 4.0 dlls did not fix our issues. Next thing we assumed was the commonly known point that this product does not support AnyCPU compilation, because it is a wrapper around the C library of SQLite. So we assumed we had a x86 / x64 issue. But this was not the case either.

Here come the solution
The point was, that with the .NET 4.0 version of SQLite the Visual C++ runtime seems to be a prerequisite. On our development machines everything worked well due to the installed Visual Studio. But on the setup machines SQLite did not work. So if you migrate from .NET 3.5 to .NET 4.0 and use SQLite, make sure the C++ runtime is installed.


  • Visual C++ Redistributable package 32 bit
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x86]
    Installed = 1 (REG_DWORD)
  • Visual C++ 2010 Redistributable package 64 bit
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\VC\VCRedist\x64]
    Installed = 1 (REG_DWORD)
Found this, besides some other useful hints here, but noticed that the 64bit registry key was slightly wrong, so be aware of that.

Native .NET SQLite
A different approach would be to use the native .NET SQLite port that can be found here. The project is not officially related to SQLite, but it is based on a current version of SQLite of 3.7.7.1. The project seems to be quite active. I hope I will be able to try it out some time. Does anyone have experiences with that?


Dienstag, 28. Juni 2011

Der Out-of-browser Schock

Ich habe unlängst versucht eine bestehende Silverlight Applikation "Out-of-browser" zu bringen. Die Applikation verwendet eine Art Bootstrapper der im Application_Startup Ereigniss gestartet wird. Dieser Bootstrapper führt eine Reihe von Serviceaufrufen durch um bestimmte Initialisierungen vorzunehmen und Daten zu laden die mein Client später braucht.

Als "In-Browser" Applikation läuft das alles super. Out-of-Browser läuft nichts mehr. Ich bekomme TimeoutExceptions bei einfachen, kurzen Serviceoperationen. Bei meinen Recherechen bin ich mehrfach auch einen Hinweis wie diesen gestoßen:

http://stackoverflow.com/questions/5432286/cross-domain-policies-in-silverlight-out-of-browser

Es handelt sich bei dem Problem nicht um ein Cross-Domain Problem - dann hätte man als Exception ja auch eher eine SecurityException erwartet.

Der Grund scheint zu sein: in einer OOB Applikation kann am aus dem Application_Startup Ereignis keine Services aufrufen bevor das Root Visual gesetzt ist. Die genannte Lösung ist, diesen Code in das Loaded-Ereignis des RootVisual zu schreiben.

Tatsächlich hilft es, das RootVisual zunächst auf ein UserControl zu setzen. Dann werden auch Serviceaufrufe aus der App.xaml.cs heraus ausgeführt. Leider kann man das RootVisual nur einmal setzen. Spätere Setzungen werden einfach ignoriert.

Ungeachtet der Tatasache ob es möglich wäre, die Applikation so umzubauen das die Serviceaufrufe erst nach der Setzung des RootVisuals erfolgen frage ich mich warum das überhaupt sein muss? Warum schafft man so einen strukturellen Unterschied zwischen In-Browser und OOB? Ich hatte gehofft das eine App "einfach so" auch Out of Browser läuft - solange sie nicht die HTML-Bridge benutzt, das versteht sich von selbst.

Ich finde es sehr schade das dies offenbar nicht möglich ist...

Anbei die Punkte die mir bei der Umstellung von In-Browser auf OOB aufgefallen sind:
  • Vor dem ersten Servicecall muss das RootVisual gesetzt werden
  • Vor der Nutzung von HtmlPage sollte mit HtmlPage.IsEnabled geprüft werden ob die HTML Bridge verfügbar ist.
Weitere Punkte werde ich ergänzen so wie sie mir auffallen :-)

Donnerstag, 24. Februar 2011

Multi Targeting mit WPF und Silverlight

Multi Targeting hilft, Code in WPF und Silverlight gemeinsam zu verwenden. Im Rahmen der BASTA Spring 2011 hatte ich die Gelegenheit einen Vortrag zu diesem spannenden Thema zu halten.

Für alle die teilgenommen haben oder die nicht Teilnehmen konnten, stelle ich hier die Demos und Folien des Vortrags zum download bereit. Ich hoffe allen Teilnehmern hat der Vortrag gefallen und ich hoffe das Sie praktische Tips mitnehmen konnten.

Der Download enthält einige Links, die komplette Demo aus dem Vortrag, die Slides und die Projekt Linker Extension für Visual Studio.

Falls Sie Fragen zu den Demos oder Folien haben, melden Sie sich einfach bei mir.

Download

Montag, 10. Januar 2011

IIS, ASP.NET 2.0 und .NET 4.0 Assemblies

Nach dem Austausch einiger Dateien innerhalb eines virtuellen IIS Verzeichnisses das Services hosted, ereilte mich folgende Fehlermeldung:

Die Datei oder Assembly "..." oder eine Abhängigkeit davon wurde nicht gefunden. Die Assembly wird von einer Laufzeit erstellt, die aktueller als die derzeit geladene Laufzeit ist, und kann nicht geladen werden.
Die Webseite welche die Services hosted basiert noch auf ASP.NET 2.0. Wie sich herausgestellt hat, ist eine Assembly die bereits auf das .NET Framework 4 als Zielframework kompiliert war mit in den "bin"-Ordner gerutscht, in dem die Assemblies für die Services lagen.

Obwohl die .NET 4.0 Assembly in keiner anderen Assmebly referenziert oder sonst wie verwendet wird, kommt es zu dem Fehler. Es scheint, das alle Assemblies geladen werden die im bin-Ordner liegen. Die Lösung war in diesem Fall also einfach: entferene die Assembly und alles ist gut.

Fazit: .NET 4.0 - ganz oder gar nicht :-)