WPF Performant viele Controls darstellen.

Wer unter WPF eigene Controls erzeugt wird sich früher oder später mit der Frage der Performance auseinander setzten müssen. Besonders wenn das eigene UserControl mehr als 100 mal auf die Oberfläche darstellt. Spätestens dann muss man sich gut überlegen, wo man in den WPF-ToolKit Baum einsteigt.

Zuerst muss man als alter DirectDraw oder WindowsForms Entwickler umdenken. Anders als früher zeichnet man nicht mehr „immidiate“. Früher wurde man vom Betriebssystem informiert, wenn sich was am Zeichenbereich geändert hat und man musste „mit der Hand am arm“ neuzeichnen. Bei WPF wird der Spieß umgedreht. Man übergibt dem WPF Subsystem eine Reihe von zu zeichnenden Objekten und wird dann nicht weiter belästigt. Das Subsystem kümmert sich um alles, was das Neuzeichnen, Überzeichnen und das Transformieren betrifft.

Die leichteste Komponente die man zeichnen kann ist eine irgendwie geartete Geometrie. Leicht im Sinne von Overhead, der vom WPF-Subsystem erzeugt wird. Will man „schnell“ viele ObjeKte Zeichnen ist es die einfachste Methode alles in einen DrawingContext/DrawingVisual zu zeichnen. Mittels ein oder mehrerer Geometries kann man die komplexesten Objekte zeichnen. Leider hat dieses Verfahren das Problem, dass man sich um alles selber kümmern muss. Es gitb keine „MouseEvents“ oder ähnliches für die Geometries. Desweiteren kann man ein DrawingVisual nur im ganzen neu zeichnen. Will man einzelne Bereiche aktualisieren muss das ganze Bild neu gezeichnet. Das kann bei vielen Objekten zu einem Problem werden.

Der bessere Weg ist da einen DrawingContainer zu nutzen. Dabei wird stellt jede darzustellende Objekt ein Geometrie dar, die in ihr eigenes DrawingVisual gezeichnet wird. Dieses wird dann in einen DrawingContainer eingebettet. Das erhöht den Overhead ein wenig, bietet dafür aber den Vorteil, dass einzelne Bereiche des Bildes neu gezeichnet werden können, ohne dass andere DrawingVisuals davon betroffen sind. Um HitTesting und „MouseEvents“ muss man sich erneut selber kümmern.

Kommt es auf Performance nicht an, kann man auch von einem UserControl oder ähnlichem ableiten und diesem ein DrawingVisual als Child verpassen. Hier hat man alle Vorzüge die das WPF so an EventHandling Bereit hält, leider geht damit auch ein erheblicher Performanceverlusst ein her.

Erster Preview des GpsGallery fertig

Die Probleme mit dem Firefox erwiesen sich als systematisch. Aus irgendeinem Grund parsen Opera und IE folgenden Code anders als der Firefox:

<html>
<div id="someName" />
<script type="text/javascript">
alert(someName);
</script>
</html>

Unter IE/Opera erscheint (wenn auch wenig sinnvoller) Text, da sie automatisch die den Div-Container mit der ID someName in die Variable someName umsetzten. Der FireFox macht das nicht, dort schreit einen einfach nur das „undefined“ an.

Nachdem ich schnell meine Scripte entsprechend angepasst habe, gebe ich das erste mal meinen Code raus, diesmal noch unversioniert. Da ich noch im „ich such mir mein optimales Versionierungstool“-Prozess bin…
Sourcecodes

SqlDependencys feuern nicht, obwohl sie korrekt initialisiert sind.

Es kann vorkommen, dass eine SqlDependency nicht gefeuert wird obwohl sie „korrekt“ initialisiert wurde und es änderungen auf der Datenbank gibt. Der Grund ist, dass auf seiten des MsSql-Servers fehler auftrahten, die nicht zum Client weiter gereicht werden. Über Sinn oder Unsinn kann man sich trefflich streiten, beheben muss man den Fehler jedoch 😉

Häuffigste Ursache eines solchen Fehlers ist das Einspielen eines (Produktiv-) Backups  in die Testumgebung. Dabei wird der DB-Owner nicht auf den User gesetzt der das Backup einspielt (es gibt dafür keine Option) und es wird auch nicht geprüft ob der DB-Owner existiert. Ist letzteres nicht der Fall, wird beim Anlegen einer Dependency versucht auf selbigen zu wechseln… mit folgendem Resultat:

„Cannot execute as the database principal because the principal „dbo“ does not exist, this type of principal cannot be impersonated, or you do not have permission.“

Dieser äußerst unschöne Umstand lässt sich dann meistens im Windows-EventLog nachlesen. Leider gibt es keine anderen Hinweise. Ist der Fehler einmal erkannt, lässt er sich leicht durch folgendes Statement beheben

USE targetDB
GO
sp_changedbowner 'targetUser'

Quelle:
Support-Microsoft

XMP Daten aus JPEG extrahieren

Da ich in meiner Gallerie Metadaten wie GPS-Koordinaten und Schlagwörter benötige hab ich mich die letzten Tage mal mit dem extrahieren von solchen daten aus dem JPEG-Format beschäfftigt.

Zuerst bin ich bei der SourceForge fündig geworden. Dort gibt es mehrere Libs zu auswahl. Die haben meistens nur ein Problem.  Entweder sie nutzen .NET WPF funktionen oder extrahieren reine EXIF-Tags.

Nachdem ich mehrere Stunden vergeblcih versucht hab mit normalen „Boardmitteln“, „BitSchubserei“ und anderer wiedrigkeiten an diese Daten zu kommen, hab ich mal den guten alten HexEditor ausgegraben. Eine Suche nach meinen benutzten Schlagwörtern brachte schnell hervor, dass die meisten Bildverarbeitungsprogramme die Tag-Daten zwei mal speichern. Einmal in den EXIF Tags und einmal im IPTC/XMP/IIM Format. Von letzterem hab ich vorher viel gelesen und Definition gefunden. Exif leider weniger…

Das Problem war, dass ich nicht wusste wo diese Daten hinterlegt waren und wie.  Der Hex-Editor brachte die denkbar  einfachste Methode zum vorschein. XMP ist in reinem XML gespeichert und dieses wird hübsch im Klartext in die Datei geschrieben. Einfach die ganze Datei einlesen, Start und End-Tag suchen, zurechtschneiden, parsen und schon hat man einen sehr angenehmen Weg sämmtliche hinterlegten Daten abzufragen.

Nachdem ich meinen „Weg“ validieren wollte fand ich dann auch einige Codebeispiele dazu. Hier das verständlichste:  Shahine.com –  Reading XMP Metadata from a JPEG using C#