Media-Dateien, Fonts einbetten in WPF Anwendungen - Mini Tutorial

Der New Yorker Nick Thuesen schrieb in seinem Blog über das Einlagern von Fonts in einer Windows Presentation Foundation (WPF) Anwendung ("Embedding and Referencing Fonts in your application and/or library"). Der Artikel beschreibt in Kürze die einfache Funktionalität, doch dass es im Endeffekt funktioniert - ist irgendwo auch ein Stück Zufall. In dem folgenden kleinen Artikel habe ich das Beispiel nach Orcas transferiert und zeige, dass die Einbettung von Resourcen nicht nur mit Fonts funktioniert, dass es sie auch in .Net 3.5 gibt - und warum es bei Nick vielleicht ein Zufall war ;-)

Aufsetzen des Projektes

Das WPF Projekt "EmbeddedResourceExample" wird über den Wizard erstellt und eine gleichnamige neue Solution angelegt. Wir verwenden Visual Studio 2008 und .Net 3.5, denn wir wollen ja schließlich was neues machen (ist natürlich nicht besonders neu, denn 3.5 unterscheidet sich hier kaum von der .Net 3.0 Version - aber es ist schön zu sehen, dass es funktioniert und aufwärts kompatibel bleibt).

Anlegen der Solution

Als nächstes erzeugen wir eine Bibliothek. Wir verwenden eine ClassLibrary. Zwar benötigen wir keine extra C# Klassen für den hier gezeigten Fall, aber der Overhead ist recht klein und in einem realen Projekt würden die Resourcen vermutlich mit entsprechend passenden Klassen zur Resourcenmanipulation begleitet. Die dabei erzeugte Klasse "Class1.cs" können wir aber beruhigt löschen - die braucht kein Mensch.

Anlegen der Library

Wichtig ist es, die Bibliothek sofort als Referenz einzutragen, sonst stehen die Resourcen nicht zur Verfügung.

Als Referenz eintragen

Einbetten von Bildern und Fonts

Ansicht auf den Solution ExplorerDann werden die Ordner für Fonts und Bilder angelegt. Mit Hilfe von Drag&Drop sammeln wir uns die Fonts und die Bilder zusammen, die wir benötigen. Beim Drag&Drop werden die Bilder automatisch kopiert und in die korrekten Verzeichnisse gelegt.

Die Solution sollte nun so aussehen wie rechts zu sehen.

Nun müssen die kopierten Dateien mit dem korrekten Property versehen werden. Das betreffende Property "Build Action"

Properties

muss auf den Wert "Resource" (NICHT als "Embedded Resource") gesetzt werden. Die restlichen Einstellungen sind meist schon korrekt. So dürfen die Dateien nicht in das Output Verzeichnis kopiert werden ("Copy to Output Directory" = "Do not copy").

Wichtig für den weiteren Prozess des Ausprobierens ist es, noch kein Build durchzuführen. Bei einem realen Projekt würde dies allerdings nicht sofort nach Zufügen und setzen der Properties erfolgen.

Das Coding

Besonders komplizierter Source Code erwartet uns auf den ersten Blick nicht. Wir tragen folgendes in die Datei "Window1.xaml" ein.

<Window x:Class="EmbeddedResourceExample.Window1"
   
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   
Title="Embedded Resources" Height="500" Width="520">

<StackPanel Margin="10">

<!--Use Font Embedded In Exe-->
<TextBlock FontFamily="/Fonts/#Federation" FontSize="25" Text="Embedded Font aus der Anwendung" />

<!--Use Font Embedded In Library-->
<TextBlock FontFamily="/EmbeddedResourceLibrary;Component/Fonts/#FederationDS9Title" FontSize="25" Text="Embedded Font aus der Bibliothek" />

<!--Use Picture Embedded In Library-->
<
Image Name="xtopia" Height="375" Width="500" Source="/EmbeddedResourceLibrary;Component/Pictures/xtopia.jpg" />

</StackPanel>

</Window>

Aber sofort nach dem Eintragen des XAML erhalten wir eine Menge von Fehlern, die darauf beruhen, dass die Resourcen Bibliothek "EmbeddedResourceLibrary" noch nicht erstellt wurde und daher nicht gefunden werden kann.

Das Ergebnis

Also werfen wir ein "Rebuild All" an, damit auch alles korrekt erstellt wird. Kurz daraufhin sehen wir folgendes Bild in Visual Studio 2008.

Das Ergebnis in Orcas

Wir sehen also, dass Visual Studio 2008 in der vorliegenden Beta 2 nicht die Fonts benutzt, die wir als Resourcen hinterlegt haben. Das gleiche Ergebnis erwartet uns in der Preview von Expression Blend 2. Die Fonts werden einfach nicht im Designmode verwendet.

Das gleiche in Blend

Drücken wir aber "F5", so erhalten wir genau das, was wir wollten.

Die Anwenung läuft

Tipps und Tricks

Als erstes will ich aufklären, warum Nicks Beispiel nur per Zufall funktionierte und leicht jeden anderen verwirren kann.

Fontnamen sind keine Dateinamen

Wie man im Coding und in dem Solution Explorer erkennt, unterscheidet der entsprechende Resource-Loader zwischen Fontnamen und Dateinamen bei Fonts. Es werden grundsätzlich Fontnamen ausgewertet, egal wie der Name der Datei lautet. Bei Nick war dies identisch, daher funktionierte es - ich wählte hier extra sehr unterschiedliche Namen.

Bibliotheken, Namen und Ordner

Bei der Verwendung von Bibliotheken für Resourcen, was ich unbedingt empfehlen würde, muss die Notation "/EmbeddedResourceLibrary;Component/" (also Bibliotheksname) beachtet werden. Ordnernamen kommen dahinter (siehe Coding).

Performanz und Speicher

Die übermäßige Verwendung von in Programmcode oder Bibliothekn eingebetten Resourcen sorgt zwar für ein schnelles Ladeverhalten bei der Darstellung, nicht aber beim Programmstart. DLLs werden geladen und verbleiben im Speicher. Wer darauf achten muss oder will, der sollte eine dynamischere Variante verwenden.

p.s.
Das Photo für das Beispiel entlieh ich aus Marc Thiele
Flickr Bibliothek und zeigt mich und Carlo Blatz auf der XTopia 2007 bei unserem Track,

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)