Entity Framework: Bilder in WPF

Wenn Sie ein Abonnement des Magazins 'DATENBANKENTWICKLER' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Entity Framework: Bilder in WPF

Im Artikel »PowerApps: Bilder in Datenbank speichern« haben wir gezeigt, wie Sie mit einer PowerApp über ein Smartphone oder ein Tablet Bilder aufnehmen und diese dann in einer Datenbank speichern. Nun wollen wir uns ansehen, wie Sie diese Bilder aus der Datenbank in einer WPF-Anwendung anzeigen, die über das Entity Framework auf die Tabellen der Datenbank zugreift.

Voraussetzung

Um die Beispiele dieses Artikels nachzuvollziehen, benötigen Sie eine Datenbank, die eine Tabelle namens Fotos enthält – genau wie die, die wir im oben genannten Artikel erstellt haben. Diese enthält ein Primärschlüsselfeld namens ID und mit dem Datentyp int sowie ein Feld namens Foto und mit dem Datentyp image. Unsere Beispieldatenbank liegt auf einem Azure-Server. Sie können aber natürlich auch unsere Beispieldatenbank mit ein paar Beispielfotos aus dem SQL-Skript aus dem Download auf einem lokalen SQL Server anlegen und mit der folgenden Anwendung auf diese Datenbank zugreifen.

Vorbereitung

Wir erstellen in Visual Studio ein neues Projekt auf Basis der Vorlage Visual Basic|Windows Desktop|WPF-App. Da wir diesmal nicht, wie so oft in den vorherigen Ausgaben, ein Code First-Model erstellen, sondern mit einer bestehenden Datenbank starten, noch einmal eine kurze Beschreibung der nötigen Schritte. Dem neuen Projekt fügen wir als Erstes ein neues Element hinzu und wählen den Typ ADO.NET Entity Data Model aus. Nachdem wir als Name FotoverwaltungContext eingestellt haben, klicken wir auf Hinzufügen (siehe Bild 1).

Einfügen des Entity Data Models

Bild 1: Einfügen des Entity Data Models

Danach wählen wir als Modellinhalt Code First aus Datenbank aus (siehe Bild 2). Der folgende Dialog bietet die Möglichkeit zur Auswahl der Datenverbindung. Hier klicken wir auf die Schaltfläche Neue Verbindung. Im nun erscheinenden Dialog namens Verbindungseigenschaften geben Sie unter Servername den Namen des gewünschten Servers ein. Danach wählen Sie die Authentifizierungsmethode aus – beim Zugriff auf eine Azure-Datenbank immer die SQL Server-Authentifizierung – und geben die Zugangsdaten ein. Schließlich wählen Sie die Datenbank aus und bestätigen nach einem erfolgreichen Test mit einem Klick auf die Schaltfläche Testverbindung die Eingaben mit OK (siehe Bild 3).

Auswahl der Datenquelle

Bild 2: Auswahl der Datenquelle

Auswahl des Typs Code First aus Datenbank

Bild 3: Auswahl des Typs Code First aus Datenbank

Danach kehren wir zum Dialog Assistent für Entity Data Model zurück, der Sie fragt, ob Sie Benutzername und Kennwort wirklich in der Verbindungszeichenfolge speichern wollen (siehe Bild 4). Für dieses Beispiel lassen wir diese Daten in der Verbindungszeichenfolge, aber im Artikel Zugangsdaten für SQL Server abfragen zeigen wir, wie Sie diese jeweils beim Start der Anwendung abfragen können.

Einstellen weiterer Eigenschaften

Bild 4: Einstellen weiterer Eigenschaften

Schließlich wählen wir im Schritt Wählen Sie Ihre Datenbankobjekte und Einstellungen noch die Tabelle aus, deren Daten wir in der Anwendung anzeigen wollen. Wir haben die Tabelle tblFotos einfach in eine bestehende Datenbank eingefügt, daher müssen wir diese einzeln auswählen (siehe Bild 5).

Auswahl der gewünschten Tabelle

Bild 5: Auswahl der gewünschten Tabelle

Dieser Dialog bietet auch noch die Option Generierte Objektnamen in den Singular oder Plural setzen an. Da die Tabelle ohnehin das Präfix tbl im Namen tblFotos enthält, das wir in unserem Entity Data Model nicht als Bezeichnung der Entität sehen wollen, müssen wir hier ohnehin noch ein Mapping vornehmen.

Nach einem Klick auf die Schaltfläche Fertigstellen finden Sie zwei neue Elemente im Projektmappen-Explorer vor: die Klasse FotoverwaltungContext.vb, die von der Klasse DbContext erbt und zum Beispiel das DbSet namens tblFotos für den Zugriff auf die Liste der Entitäten auf Basis der in der Tabelle gespeicherten Daten bereitstellt sowie die Klasse tblFotos.vb als Entitätsklasse für einen Datensatz der Tabelle tblFotos.

Die Benennung der Klasse und des Namens des DbSet-Elements entspricht nicht unseren Vorstellungen, also ändern wir das ein wenig ab. Wie das genau gelingt, zeigen wir Ihnen im Artikel EDM für bestehende Datenbank mit Code First. Zum schnellen Nachbauen hier die notwendigen Änderungen. Als Erstes ändern wir den Namen der Klasse tblFotos.vb in Foto.vb.

In der Klasse Foto.vb müssen wir den Namen der Eigenschaft Foto in Fotodaten ändern, da keine Eigenschaft genauso heißen darf wie die Klasse:

Partial Public Class Foto
     Public Property ID As Integer
     <Column(TypeName:="image")>
     <Required>
     Public Property Fotodaten As Byte()
End Class

Damit die Klasse Foto auf die Tabelle tblFotos gemappt wird und die Eigenschaft Fotodaten der Klasse auf das Feld Foto der Tabelle, fügen wir folgende Zeilen zur Methode OnModelCreating der Klasse FotoverwaltungContext.vb hinzu:

Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)
     modelBuilder.Entity(Of Foto)().
         ToTable("tblFotos").
         Property(Function(t) t.Fotodaten).HasColumnName("Foto")
End Sub

Damit können wir nun testen, ob der Zugriff auf die Datensätze der Tabelle tblFotos gelingt. Dazu fügen wir der Klasse MainWindow.xaml.vb zunächst eine Konstruktor-Methode hinzu. In dieser erstellen wir einen Datenbankkontext für den Zugriff auf die Datenbank. Außerdem versuchen wir, auf das erste Element der Auflistung Fotos dieses Kontextes zuzugreifen und den Inhalt der Eigenschaften ID und Fotodaten in einem Meldungsfenster auszugeben:

Class MainWindow
     Public Sub New()
         Dim dbContext As FotoverwaltungContext
         dbContext = New FotoverwaltungContext
         Dim foto As Foto
         foto = dbContext.Fotos.First()
         MessageBox.Show(foto.ID.ToString() + vbCrLf + vbCrLf + foto.Fotodaten.ToString())
     End Sub
End Class

Sofern Sie bereits einen Datensatz zu dieser Tabelle hinzugefügt haben, werden die entsprechenden Informationen beim Start der Anwendung ausgegeben.

Bild im WPF-Fenster anzeigen

Nun schauen wir uns an, wie wir den Inhalt der Eigenschaft Fotodaten, also des Feldes Foto der Tabelle tblFotos, in einem Steuer­element in einem WPF-Fenster anzeigen. Dazu benötigen wir zunächst ein geeignetes Steuer­element. Wir fügen dem Fenster MainWindow.xaml zunächst ein Image-Steuerelement hinzu, das wir mit dem Bild aus der Eigenschaft Fotodaten füllen wollen. Das Steuer­element ziehen wir einfach aus der Toolbox in das WPF-Fenster. Dadurch entsteht etwa der folgende XAML-Code:

<Image HorizontalAlignment="Left" Height="288" Margin="112,50,0,0" VerticalAlignment="Top" Width="364"/>

Das Bild ist im Feld Foto der Tabelle tblFotos unter dem Datentyp image gespeichert (siehe Bild 6). Wir müssen nun einen Weg finden, den Inhalt dieses Feldes im Image-Steuerelement anzuzeigen.

Das Feld Foto in der Tabelle tblFotos

Bild 6: Das Feld Foto in der Tabelle tblFotos

Dazu verarbeiten wir dieses zunächst in der Code behind-Klasse MainWindow.xaml.vb. Hier verschieben wir die Deklaration des Datenbankkontexts zunächst aus der Konstruktor-Methode in den allgemeinen Teil der Klasse:

Class MainWindow
     Dim dbContext As FotoverwaltungContext

Dann deklarieren wir eine private Variable namens m_Fotodaten mit dem Datentyp BitmapImage, die wir über die folgende Property namens Fotodaten mit dem gleichen Datentyp für den lesenden und schreibenden Zugriff verfügbar machen:

     Dim m_Fotodaten As BitmapImage
     Public Property Fotodaten As BitmapImage
         Get
             Return m_Fotodaten
         End Get
         Set(value As BitmapImage)
             m_Fotodaten = value
         End Set
     End Property

Danach erweitern wir die Konstruktor-Methode New. Nach dem Zuweisen des Datenbankkontextes zur Variablen dbContext deklarieren wir ein Objekt des Typs Foto und weisen diesem das erste Element der mit der Auflistung Fotots eingelesenen Tabelle tblFotos zu:

     Public Sub New()
         dbContext = New FotoverwaltungContext
         Dim foto As Foto
         foto = dbContext.Fotos.First()

Dann lesen wir zunächst den Inhalt der Eigenschaft Fotodaten (also eigentlich des Feldes Foto der Tabelle tblFotos) in ein Objekt des Typs Byte mit dem Namen blob ein. Danach erstellen wir ein Objekt namens stream mit dem Typ MemoryStream, in das wir den Inhalt des Byte-Arrays blob mit der Write-Methode schreiben. Dann stellen wir die Position des Stream-Objekts auf die Position 0 ein:

         Dim blob As Byte() = foto.Fotodaten
         Dim stream As MemoryStream = New MemoryStream()
         stream.Write(blob, 0, blob.Length)
         stream.Position = 0

Nun kommt erstmals das Objekt des Typs BitmapImage ins Spiel, das wir anschließend auch dem Image-Steuerelement als Quelle zuweisen können. Dieses erstellen wir unter dem Namen img und initialisieren es mit der Methode BeginInit. Dann weisen wir als StreamSource den Inhalt der MemoryStream-Variablen stream zu und beenden die Initialisierung von img mit der EndInit-Methode:

         Dim img As BitmapImage
         img = New BitmapImage
         img.BeginInit()
         img.StreamSource = stream
         img.EndInit()

Schließlich weisen wir img der öffentlichen Eigenschaft Fotodaten zu und stellen die aktuelle Klasse als DataContext der WPF-Seite ein:

         Fotodaten = img
         DataContext = Me
     End Sub
End Class

Danach müssen wir nur noch der Eigenschaft Source des Image-Elements im XAML-Code den Pfad zur Eigenschaft Fotodaten mitteilen:

<Image HorizontalAlignment="Left" Height="288" Margin="112,50,0,0" VerticalAlignment="Top" Width="364" Source="{Binding Path=Fotodaten}"/>

*****Bild mit Bild*****

Durch Bilder blättern

Wenn wir nun nicht nur ein Bild anzeigen, sondern auch durch alle vorhandenen Bilder blättern wollen, benötigen wir prinzipiell die gleichen Techniken, die wir auch sonst zum Blättern in Datensätzen verwenden. Dazu erstellen wir ein neues Fenster namens FotosBlaettern.xaml. Dieses öffnen wir vom Startfenster MainWindow.xaml aus mit einer neuen Schaltfläche, der wir die folgenden Codezeilen hinzufügen:

Private Sub btnBeispielZumBlaettern_Click(sender As Object, e As RoutedEventArgs)
     Dim wnd As FotosBlaettern
     wnd = New FotosBlaettern
     wnd.ShowDialog()
End Sub

Die Techniken, die wir weiter oben kennengelernt haben, können wir für das Blättern durch Datensätze mit Bildern ebenfalls verwenden. Außerdem nutzen wir einige Techniken, die wir im Artikel EDM: Blättern in Datensätzen vorgestellt haben. Im XAML-Code verwenden wir in den Ressourcen einige DataTrigger, mit denen wir die Schaltflächen aktivieren und deaktivieren wollen (siehe ebenfalls im oben genannten Artikel):

<Window x:Class="FotosBlaettern" ... Title="FotosBlaettern" Height="450" Width="800">
     <Window.Resources>
         <Style x:Key="ButtonVorheriger" TargetType="{x:Type Button}">
             <Style.Triggers>
                 <DataTrigger Binding="{Binding Erster}" Value="False">
                     <Setter Property="IsEnabled" Value="False"></Setter>
                 </DataTrigger>

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.