Dienstag, 23. November 2010

Erstellen eines CommandLink in der WPF - Teil 1

Einleitung
Immer wieder bin ich auf der Suche nach einem Thema, über welches ich einen Blog-Post verfassen kann. Und so bin ich kürzlich wieder über das Thema CommandLink-Button gestolpert. Da dieser weder in WinForms, noch in der WPF out-of-the-box unterstützt wird, möchte ich ein kleines Tutorial über die Entwicklung eines CommandLink-Button als CustomControl in WPF erstellen. Nicht zuletzt dient dieses Tutorial auch dazu, Erlerntes weiter zu verfestigen. Bei der Entwicklung des Controls sollen die Windows User Experience Guidelines eingehalten werden. Damit der Beitrag nicht zu lange wird teile ich ihn in kleine Beiträge auf und werde von Zeit zu Zeit eine Fortsetzung posten.

Anforderungen an den CommandLink-Button
Bevor ich mit der Entwicklung des CommandLinks beginne, muss ich herausfinden wie der CommandLink ab Windows-Vista funktioniert. Dazu analysiere ich zunächst die unterschiedlichen Zustände die er Button einnehmen kann.
  • Normal
  • MouseOver
  • MouseOver + Focused
  • Focused
  • Pressed
Die fünf möglichen Zustände sind nun ermittelt. Als nächstes stellt sich die Frage welchen Inhalt ein solcher CommandLink anzeigen kann. Wer Windows-Vista oder Windows 7 kennt, weis, dass in den dortigen CommandLinks nicht nur Text vorkommt. Sie enthalten oft noch Details zur anstehenden Aktion, wie z.B. beim Überschreiben von Dateien. Dennoch sind ganz klare feste Bestandteile zu erkennen.
  • Icon oder grüner Pfeil / Schutzschild
  • Titel in grosser Schrift
  • Beschreibungstext unterhalb des Titels mit kleiner Schrift
  • (Details in unterschiedlichen Ausführungen)

CommandLink unter Windows 7

Fester Bestandteil des CommandLink sind, das Icon, Titel und Beschreibungstext. Details unterhalb des Beschreibungstextes sind optional und können je nach Scenario variieren. Der CommandLink soll als eigenständiges CustomControl erstellt werden. Dennoch möchte ich vermeiden sämtliche Logik von Grund auf neu schreiben zu müssen. Deshalb ziehe ich es vor, den CommandLink von einem bestehenden und funktional möglichst ähnlichem Control abzuleiten. Nichts liegt dabei näher, als das bereits im Framework vorhande Button-Control.

Fortsetzung folgt...

Montag, 22. November 2010

Dotnetpro Dojo Dezember

Wie viele Blätter hat der Baum
Heute habe ich mich mal dem Dojo aus der aktuellen Dotnetpro gewidmet. Primär möchte ich damit üben hier im Blog zu dokumentieren und die Gedankengänge nieder zu schreiben. Bei dem Dojo selbst geht es um eine API die Bäume abbildet und deren Inhalt ausgeben kann. Es ist eines der einfacheren Dotnetpro Dojos. In der Aufgabenstellung sind zwei generische Interfaces vorgegeben die zu implementieren sind.











Bei der Implementierung soll besonderes Augenmerk auf die beiden Methoden PreOrderValues() und PostOrderValues() gelegt werden. Diese dienen dazu den Inhalt der Bäume zu durchlaufen. Genau hier liegt aber der Knackpunkt, denn welchen Weg nimmt man beim Durchlaufen eines Baums? Anders als bei gewöhnlichen Listen gibt es hier nicht nur einen Start und Endpunkt. Zu den beiden Methoden werden zwei Beispiele geliefert um die Wege zu demonstrieren so einen Baum zu durchlaufen.
  • Wurzel als Startpunkt - Diese Variante gibt zunächst das Wurzelelement zurück. Dann die Kind-Elemente des Wurzelelements und wiederum deren Kind-Elemente usw.
  • Blätter als Startpunkt - Diese Variante fungiert gerade umgekehrt. Sie beginnt bei den Blättern und gibt damit zunächst die äussersten Elemente zurück, um sich anschliessend immer weiter bis zur Wurzel voranzuarbeiten.

Unit-Test
Für die Durchführung des Dojos werden automatisierte Unit-Tests gefordert. Deshalb beginne ich zunächst diese Tests einzurichten, damit ich meine spätere Arbeit direkt überprüfen kann. Ich nutze dazu das kostenlose Framework NUnit.

Ich habe nun zwei Test-Methoden erstellt die jweils eine der beiden oben genannten Durchlauf-Varianten testen. Da die beiden Interfaces bereits vorhanden sind konnte ich fast den kompletten Testcode bereits im Voraus fertigstellen. Lediglich eine Instanz des Tree mit dem Root-Node fehlt noch.






















Der erste Unit-Test schlägt in diesem Zustand natürlich auch prompt fehl, da es zu einer NullReferenceException kommt. Nicht weiter verwunderlich.


Implementierung der Interfaces
Es wird nun also Zeit die Klassen zu erstellen, welche die beiden Interfaces implementieren. Dazu lege ich die generischen Klassen Tree und Node an. Hierbei übernimmt zunächst Visual Studio die meiste Arbeit, indem es die Eigenschafts- und Methodenrümpfe erstellt, die von den Interfaces gefordert werden.

Bevor ich jedoch mit der Implementierung des Codes beginne, denke ich zunächst darüber nach wie die beiden Klassen instantiiert werden sollen. Gut zu erkennen ist ja bereits die durch das Interface INode vorgegebene Add-Methode. Sie nimmt einen Parameter vom Typ T entgegen und gibt eine INode(Of T) zurück. Somit muss innerhalb der Methode aus dem Parameter vom Typ T eine Node werden welche diesen kapselt. Da die Value-Eigenschaft einer INode nur les- und nicht schreibbar ist, muss der Wert über den Konstruktor der Node -Klasse injiziert werden.

Wenn einer Node eine Child-Node mit Hilfe der Add-Methode hinzugefügt wird, dann muss diese neue Child-Node auch innerhalb der Node gespeichert werden. Dazu benötige ich ein privates Feld.

Der Wert der für eine Node im Konstruktor angegeben wird muss natürlich ebenso gespeichert werden. Dazu gibt es ebenfalls ein privates Feld in der Klasse Node.

Die Eigenschaften Value, Children und ChildValues sind leicht zu implementieren. Sie geben lediglich die Inhalte der beiden privaten Felder zurück.

Zuletzt noch die Klasse Tree. Sie beinhaltet bisher eine Eigenschaft vom Typ INode(Of T). Dabei handelt es sich um das Wurzelelement. Da ein Baum nicht existieren kann ohne eine Wurzel zu haben, soll der Wert für das Wurzelelement direkt im Konstruktor des Baums angegeben.

Todo-Liste:
  • Konstruktor für Node mit Wert von Typ T als Parameter
  • Privates Feld um Child-Nodes zu speichern.
  • Privates Feld um Inhalt/Wert der Node zu speichern
  • Eigenschaften Value, Children und ChildValues an den Inhalt der privaten Felder anbinden
  • Konstruktor für Tree mit der von Typ T als Parameter
Genug darüber nachgedacht. Diese Liste kann erstmal abgearbeitet werden bevor ich mir Gedanken über die beiden Methoden PostOrderValues() und PreOrderValues() mache.

Der Code ist nun bis auf die beiden Methoden implementiert. Erstmals können nun auch die beiden Methoden des Unit-Test komplettiert werden indem die beiden Tree-Felder mit Tree-Instanzen gefüllt werden.

tree = New Tree(Of Int32)(1)

Führe ich den Unit-Test nun aus, wird er erneut fehlschlagen. Dieses Mal jedoch erst an späterer Stelle, nämlich nach dem Aufruf der Methoden PostOrderValues() und PreOrderValues(). Diese liefern noch eine Null-Referenz was in den Assertions für die entsprechenden Fehler sorgt.


Die Methode PreOrderValues
Nun ist es soweit und die beiden Methoden kommen an die Reihe.

Nochmal das Ergebnis des Beispiels bzw. der Methode PreOrderValues() anschauen:
{1, 2, 5, 6, 3, 7, 8, 4, 9, 10}

Zunächst wird der Inhalt der Root-Node (1) ausgegeben, dann der Inhalt der ersten Child-Node (2) und zuletzt der Inhalt der beiden Child-Nodes (5, 6) der Child-Node (2).

Was bedeutet das nun für die Methode PreOrderValues? Auf Root-Ebene soll die Methode in dem Beispiel eine Liste mit den oben genannten 10 Werten zurückgeben. Auf zweiter Ebene eine Liste mit 3 Elementen und auf letzter Ebene eine Liste mit einem Element. Auf letzter Ebene kann die Methode nur den Inhalt der Node Instanz zurückgeben da keine Child-Nodes vorhanden sind. Es ergibt sich also die Bedingung: Wenn keine Child-Nodes vorhanden, dann besteht die Ergebnisliste nur aus mir selbst. Sind Child-Nodes vorhanden besteht die Ergebnisliste aus mir selbst + deren Ergebnislisten.



Die Methode PostOrderValues
Der Unterschied zur Methode PreOrderValues liegt darin, dass diese zunächst den Wert der zugehörigen Node selbst ausgibt und anschliessend die Werte der Child-Nodes. Diese Methode soll es umgekehrt tun, zunächst die Werte der Child-Nodes und anschliessend den eigenen. Was liegt also näher als einfach die Reihenfolge des Codings zu verdrehen? Gesagt getan, und siehe da es funktioniert.



Zusammenfassung
Das Dojo war bestens geeignet um einen Blog-Post zu verfassen. Es war simpel und schnell gemacht, so dass ich mich mehr um das aufschreiben kümmern konnte. Doch genau dies ist auch die Intention der Dotnetpro Dojos - es geht nicht um das Coding selbst, sondern um das drum herum.

Finally :-)

Montag, 19. April 2010

Webseite-Tests mit dem Internet Explorer

Jeder Web-Entwickler wird seine Webseite einmal in unterschiedlichen Web-Browsern betrachten und testen. Gerade wenn noch die Version 6 des Internet Explorer unterstützt werden soll ist dies unerlässlich.

Bisher habe ich dazu die virtualisierten Browser von Xenocode verwendet. Diese haben jedoch unter Windows 7 nicht mehr korrekt funktioniert und ich habe mich erneut umgeschaut. Dabei bin ich über Beiträge gestolpert die empfohlen haben die virtualisierten Browser von Xenocode nicht mehr zu verwenden. Gleichzeitung wurde eine Alternative vorgeschlagen welche mir bisher unbekannt war, bei mir jedoch einen positiven Eindruck hinterlassen hat. Dabei geht es um den IETester der im modernen Ribbon-Bar Design daherkommt. Er unterstützt dabei die Rendering- und Javascript-Engines des IE8, IE7, IE6 und IE5.5 bis Windows 7.

Link: IETester auf my-debugbar.com

Video: SketchFlow in 90 seconds, with Jon Harris