Freigeben über


Aktualisieren und Löschen von vorhandenen Binärdaten (VB)

von Scott Mitchell

PDF herunterladen

In früheren Lernprogrammen haben wir gesehen, wie das GridView-Steuerelement das Bearbeiten und Löschen von Textdaten vereinfacht. In diesem Lernprogramm wird gezeigt, wie das GridView-Steuerelement auch das Bearbeiten und Löschen von Binärdaten ermöglicht, unabhängig davon, ob diese Binärdaten in der Datenbank gespeichert oder im Dateisystem gespeichert werden.

Einleitung

In den letzten drei Lernprogrammen haben wir einige Funktionen für die Arbeit mit Binärdaten hinzugefügt. Wir haben damit begonnen, der Tabelle eine BrochurePath Spalte Categories hinzuzufügen und die Architektur entsprechend zu aktualisieren. Außerdem wurden Methoden für die Datenzugriffsschicht und die Geschäftslogikebene hinzugefügt, um mit der vorhandenen Spalte Picture der "Categories"-Tabelle zu arbeiten, die die binären Inhalte einer Bilddatei enthält. Wir haben Webseiten erstellt, um die Binärdaten in einem GridView-Downloadlink für die Broschüre darzustellen, wobei das Kategoriebild in einem <img> Element angezeigt wird und eine DetailsView hinzugefügt haben, damit Benutzer eine neue Kategorie hinzufügen und ihre Broschüren- und Bilddaten hochladen können.

Alles, was noch implementiert werden muss, ist die Möglichkeit, vorhandene Kategorien zu bearbeiten und zu löschen, die wir in diesem Lernprogramm mithilfe der integrierten Bearbeitungs- und Löschfunktionen von GridView durchführen werden. Beim Bearbeiten einer Kategorie kann der Benutzer optional ein neues Bild hochladen oder die Kategorie weiterhin die vorhandene verwenden. Für die Broschüre können sie entweder die vorhandene Broschüre verwenden, eine neue Broschüre hochladen oder angeben, dass der Kategorie keine Broschüre mehr zugeordnet ist. Los geht's!

Schritt 1: Aktualisieren der Datenzugriffsschicht

Die DAL verfügt über automatisch generierte Insert, Updateund Delete Methoden, aber diese Methoden wurden basierend auf der CategoriesTableAdapter Hauptabfrage generiert, die die Picture Spalte nicht enthält. Daher enthalten die Insert und Update Methoden keine Parameter zum Angeben der Binärdaten für das Bild der Kategorie. Wie im vorherigen Lernprogramm müssen wir beim Angeben von Binärdaten eine neue TableAdapter-Methode zum Aktualisieren der Categories Tabelle erstellen.

Öffnen Sie das typisierte DataSet, klicken Sie im Designer mit der rechten Maustaste auf die CategoriesTableAdapter-Kopfzeile und wählen Sie im Kontextmenü "Abfrage hinzufügen" aus, um den Konfigurations-Assistenten für TableAdapter-Abfragen zu starten. Dieser Assistent fragt uns zunächst, wie die TableAdapter-Abfrage auf die Datenbank zugreifen soll. Wählen Sie "SQL-Anweisungen verwenden" aus, und klicken Sie auf "Weiter". Der nächste Schritt fragt nach dem Typ der Abfrage, die generiert werden soll. Da wir eine Abfrage erstellen, um der Categories Tabelle einen neuen Datensatz hinzuzufügen, wählen Sie AKTUALISIEREN aus, und klicken Sie auf 'Weiter'.

Wählen Sie die UPDATE-Option aus.

Abbildung 1: Auswählen der UPDATE-Option (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Jetzt müssen wir die UPDATE SQL-Anweisung angeben. Der Assistent schlägt automatisch eine UPDATE Anweisung vor, die der Hauptabfrage des TableAdapter entspricht (eine, die die Werte von CategoryName, Description und BrochurePath aktualisiert). Ändern Sie die Anweisung so, dass die Picture Spalte zusammen mit einem @Picture Parameter enthalten ist, z. B.:

UPDATE [Categories] SET 
    [CategoryName] = @CategoryName, 
    [Description] = @Description, 
    [BrochurePath] = @BrochurePath ,
    [Picture] = @Picture
WHERE (([CategoryID] = @Original_CategoryID))

Der letzte Bildschirm des Assistenten fordert uns auf, die neue TableAdapter-Methode zu benennen. Geben Sie die Eingabetaste UpdateWithPicture ein, und klicken Sie auf "Fertig stellen".

Benennen der neuen TableAdapter-Methode UpdateWithPicture

Abbildung 2: Benennen der neuen TableAdapter-Methode UpdateWithPicture (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Schritt 2: Hinzufügen der Business Logic Layer-Methoden

Zusätzlich zum Aktualisieren des DAL müssen wir die BLL aktualisieren, um Methoden zum Aktualisieren und Löschen einer Kategorie einzuschließen. Dies sind die Methoden, die über die Präsentationsebene aufgerufen werden.

Zum Löschen einer Kategorie können wir die CategoriesTableAdapter automatisch generierte Delete Methode verwenden. Fügen Sie der CategoriesBLL-Klasse die folgende Methode hinzu:

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Delete, True)> _
Public Function DeleteCategory(ByVal categoryID As Integer) As Boolean
    Dim rowsAffected As Integer = Adapter.Delete(categoryID)
    ' Return true if precisely one row was deleted, otherwise false
    Return rowsAffected = 1
End Function

In diesem Lernprogramm erstellen wir zwei Methoden zum Aktualisieren einer Kategorie: eine, die die binären Bilddaten erwartet und die soeben hinzugefügte UpdateWithPicture-Methode in CategoriesTableAdapter aufruft, und eine andere, die nur die CategoryName, Description und BrochurePath Werte akzeptiert und die automatisch generierte CategoriesTableAdapter-Anweisung der Update-Klasse verwendet. Der Grund für die Verwendung von zwei Methoden besteht darin, dass ein Benutzer in einigen Fällen das Kategoriebild zusammen mit seinen anderen Feldern aktualisieren möchte, in diesem Fall muss der Benutzer das neue Bild hochladen. Die hochgeladenen Bild-Binärdaten können dann in der UPDATE Anweisung verwendet werden. In anderen Fällen ist der Benutzer möglicherweise nur daran interessiert, den Namen und die Beschreibung zu aktualisieren. Wenn die UPDATE Anweisung aber auch die Binärdaten für die Picture Spalte erwartet, müssen wir diese Informationen ebenfalls bereitstellen. Dies würde eine zusätzliche Reise in die Datenbank erfordern, um die Bilddaten für den zu bearbeitenden Datensatz zurückzubringen. Deshalb wollen wir zwei UPDATE Methoden. Die Geschäftslogikebene bestimmt, welche Entscheidung getroffen werden soll, je nachdem, ob Bilddaten beim Aktualisieren der Kategorie bereitgestellt werden.

Um dies zu erleichtern, fügen Sie der CategoriesBLL-Klasse zwei Methoden hinzu, die beide UpdateCategory heißen. Der erste sollte drei String s, ein Byte-Array und ein Integer als Eingabeparameter akzeptieren; der zweite, nur drei String s und ein Integer. Die String Eingabeparameter beziehen sich auf den Namen, die Beschreibung und den Dateipfad der Broschüre, das Byte Array ist für den binären Inhalt des Kategoriebilds bestimmt und Integer identifiziert die CategoryID des zu aktualisierenden Datensatzes. Beachten Sie, dass die erste Überladung die zweite aufruft, wenn das übergebene Byte Array folgendes ist Nothing:

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Update, False)> _
Public Function UpdateCategory(categoryName As String, description As String, _
    brochurePath As String, picture() As Byte, categoryID As Integer) As Boolean
    
    ' If no picture is specified, use other overload
    If picture Is Nothing Then
        Return UpdateCategory(categoryName, description, brochurePath, categoryID)
    End If
    ' Update picture, as well
    Dim rowsAffected As Integer = Adapter.UpdateWithPicture _
        (categoryName, description, brochurePath, picture, categoryID)
    ' Return true if precisely one row was updated, otherwise false
    Return rowsAffected = 1
End Function
<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Update, True)> _
Public Function UpdateCategory(categoryName As String, description As String, _
    brochurePath As String, categoryID As Integer) As Boolean
    Dim rowsAffected As Integer = Adapter.Update _
        (categoryName, description, brochurePath, categoryID)
    ' Return true if precisely one row was updated, otherwise false
    Return rowsAffected = 1
End Function

Schritt 3: Kopieren der Funktion "Einfügen" und "Ansicht"

Im vorherigen Lernprogramm haben wir eine Seite mit dem Namen UploadInDetailsView.aspx erstellt, die alle Kategorien in einer GridView aufgelistet und eine DetailsView bereitgestellt hat, um dem System neue Kategorien hinzuzufügen. In diesem Lernprogramm erweitern wir die GridView so, dass die Bearbeitungs- und Löschunterstützung eingeschlossen wird. Anstatt weiter zu arbeiten, UploadInDetailsView.aspx wollen wir stattdessen die Änderungen dieses Tutorials auf der UpdatingAndDeleting.aspx Seite aus demselben Ordner platzieren. ~/BinaryData Kopieren Sie das deklarative Markup und den Code von UploadInDetailsView.aspx bis UpdatingAndDeleting.aspx.

Öffnen Sie zunächst die UploadInDetailsView.aspx Seite. Kopieren Sie alle deklarativen Syntaxen innerhalb des <asp:Content> Elements, wie in Abbildung 3 dargestellt. Öffnen Sie als Nächstes UpdatingAndDeleting.aspx und fügen Sie dieses Markup innerhalb des <asp:Content> Elements ein. Kopieren Sie auf ähnliche Weise den Code aus der Code-Behind-Klasse der UploadInDetailsView.aspx-Seite in UpdatingAndDeleting.aspx.

Kopieren des deklarativen Markups aus UploadInDetailsView.aspx

Abbildung 3: Kopieren des deklarativen Markups aus UploadInDetailsView.aspx (Klicken, um das Bild in voller Größe anzuzeigen)

Nachdem Sie das deklarative Markup und den Code kopiert haben, besuchen Sie UpdatingAndDeleting.aspx. Sie sollten die gleiche Ausgabe sehen und dieselbe Benutzeroberfläche wie die Seite UploadInDetailsView.aspx aus dem vorherigen Lernprogramm haben.

Schritt 4: Hinzufügen von Löschunterstützung zur ObjectDataSource und GridView

Wie wir im Tutorial Ein Überblick über das Einfügen, Aktualisieren und Löschen von Daten besprochen haben, bietet die GridView integrierte Löschfunktionen, und diese Funktionen können durch Ankreuzen eines Kontrollkästchens aktiviert werden, wenn die zugrunde liegende Datenquelle der GridView das Löschen unterstützt. Derzeit wird das Löschen durch das ObjectDataSource, an das die GridView gebunden ist (CategoriesDataSource), nicht unterstützt.

Um dies zu beheben, klicken Sie im Smarttag von ObjectDataSource auf die Option "Datenquelle konfigurieren", um den Assistenten zu starten. Der erste Bildschirm zeigt, dass die ObjectDataSource für die Arbeit mit der CategoriesBLL Klasse konfiguriert ist. Klicken Sie auf "Weiter". Derzeit sind nur die ObjectDataSource-InsertMethod und SelectMethod-Eigenschaften angegeben. Der Assistent hat jedoch die Dropdownlisten in den Registerkarten UPDATE und DELETE automatisch mit den Methoden UpdateCategory und DeleteCategory entsprechend gefüllt. Dies liegt daran, dass wir diese Methoden in der CategoriesBLL Klasse als DataObjectMethodAttribute Standardmethoden zum Aktualisieren und Löschen markiert haben.

Legen Sie nun die Dropdownliste der AKTUALISIEREN-Registerkarte auf (Keine) fest, lassen Sie jedoch die Dropdownliste der LÖSCHEN-Registerkarte auf DeleteCategory. Wir kehren in Schritt 6 zu diesem Assistenten zurück, um den Updatesupport hinzuzufügen.

Konfigurieren der ObjectDataSource für die Verwendung der DeleteCategory-Methode

Abbildung 4: Konfigurieren der ObjectDataSource für die Verwendung der DeleteCategory Methode (Klicken, um das Bild in voller Größe anzuzeigen)

Hinweis

Nach Abschluss des Assistenten fragt Visual Studio möglicherweise, ob Sie Felder und Schlüssel aktualisieren möchten, wodurch die Felder der Daten-Websteuerelemente neu generiert werden. Wählen Sie "Nein" aus, da durch die Auswahl von "Ja" alle Feldanpassungen überschrieben werden, die Sie möglicherweise vorgenommen haben.

Die ObjectDataSource enthält nun einen Wert für seine DeleteMethod Eigenschaft sowie einen DeleteParameter. Denken Sie daran, dass Visual Studio bei Verwendung des Assistenten zum Angeben der Methoden die ObjectDataSource s-Eigenschaft OldValuesParameterFormatString auf original_{0}legt, die Probleme mit den Aufrufen der Aktualisierungs- und Löschmethode verursacht. Löschen Sie daher entweder diese Eigenschaft vollständig, oder setzen Sie sie auf die Standardeinstellung zurück. {0} Wenn Sie Ihr Gedächtnis für diese ObjectDataSource-Eigenschaft auffrischen müssen, lesen Sie das Lernprogramm Ein Überblick über das Einfügen, Aktualisieren und Löschen von Daten.

Nach Abschluss des Assistenten und der Behebung des OldValuesParameterFormatString sollte das deklarative Markup des ObjectDataSource wie folgt aussehen:

<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="{0}" SelectMethod="GetCategories" 
    TypeName="CategoriesBLL" InsertMethod="InsertWithPicture" 
    DeleteMethod="DeleteCategory">
    <InsertParameters>
        <asp:Parameter Name="categoryName" Type="String" />
        <asp:Parameter Name="description" Type="String" />
        <asp:Parameter Name="brochurePath" Type="String" />
        <asp:Parameter Name="picture" Type="Object" />
    </InsertParameters>
    <DeleteParameters>
        <asp:Parameter Name="categoryID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

Nachdem Sie die ObjectDataSource konfiguriert haben, fügen Sie der GridView Löschfunktionen hinzu, indem Sie das Kontrollkästchen "Löschen" aus dem Smarttag "GridView" aktivieren. Dadurch wird ein CommandField zu der GridView hinzugefügt, dessen ShowDeleteButton-Eigenschaft auf True festgelegt ist.

Aktivieren der Unterstützung für das Löschen in gridView

Abbildung 5: Aktivieren der Unterstützung für das Löschen in der GridView (Klicken, um das Bild in voller Größe anzuzeigen)

Nehmen Sie sich einen Moment Zeit, um die Löschfunktion zu testen. Es gibt einen Fremdschlüssel zwischen den Products Tabellen CategoryID und den Categories Tabellen CategoryID, sodass Sie eine Ausnahme wegen Verletzung der Fremdschlüsselkondition erhalten, wenn Sie versuchen, eine der ersten acht Kategorien zu löschen. Um diese Funktionalität zu testen, fügen Sie eine neue Kategorie hinzu, die sowohl eine Broschüre als auch ein Bild bereitstellt. Meine Testkategorie, die in Abbildung 6 dargestellt ist, enthält eine Testprospektdatei mit dem Namen Test.pdf und einem Testbild. Abbildung 7 zeigt die GridView, nachdem die Testkategorie hinzugefügt wurde.

Hinzufügen einer Testkategorie mit einer Broschüre und einem Bild

Abbildung 6: Hinzufügen einer Testkategorie mit einer Broschüre und einem Bild (Klicken, um das Bild in voller Größe anzuzeigen)

Nach dem Einfügen der Testkategorie wird sie in der GridView angezeigt.

Abbildung 7: Nach dem Einfügen der Testkategorie wird sie in der GridView angezeigt (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Aktualisieren Sie in Visual Studio den Lösungs-Explorer. Nun sollte eine neue Datei im ~/Brochures Ordner Test.pdf angezeigt werden (siehe Abbildung 8).

Als Nächstes klicken Sie auf den Link "Löschen" in der Zeile "Testkategorie", wodurch ein Postback der Seite ausgelöst wird und die Methode der CategoriesBLL Klasse DeleteCategory gestartet wird. Dadurch wird die DAL s-Methode Delete aufgerufen, wodurch die entsprechende DELETE Anweisung an die Datenbank gesendet wird. Die Daten werden dann an das GridView-Objekt zurückgesendet, und das Markup wird an den Client zurückgesendet, wobei die Testkategorie nicht mehr vorhanden ist.

Während der Löschworkflow den Datensatz "Testkategorie" erfolgreich aus der Categories Tabelle entfernt hat, wurde die Broschürendatei nicht aus dem Dateisystem des Webservers entfernt. Aktualisieren Sie den Projektmappen-Explorer, und Sie werden sehen, dass Test.pdf sich noch im ~/Brochures Ordner befindet.

Die Test.pdf Datei wurde nicht aus dem Dateisystem des Webservers gelöscht.

Abbildung 8: Die Test.pdf Datei wurde nicht aus dem Dateisystem des Webservers gelöscht.

Schritt 5: Entfernen der Broschürendatei der gelöschten Kategorie

Einer der Nachteile beim Speichern von Binärdaten außerhalb der Datenbank besteht darin, dass zusätzliche Schritte unternommen werden müssen, um diese Dateien zu bereinigen, wenn der zugeordnete Datenbankdatensatz gelöscht wird. GridView und ObjectDataSource stellen Ereignisse bereit, die sowohl vor als auch nach der Ausführung des Löschbefehls ausgelöst werden. Wir müssen tatsächlich Ereignishandler für die Ereignisse vor und nach der Aktion erstellen. Bevor der Categories Datensatz gelöscht wird, müssen wir den Pfad der PDF-Datei ermitteln, aber wir möchten die PDF-Datei nicht löschen, bevor die Kategorie gelöscht wird, falls es eine Ausnahme gibt und die Kategorie nicht gelöscht wird.

Das GridView-Ereignis RowDeleting wird ausgelöst, bevor der Löschbefehl von ObjectDataSource aufgerufen wurde, während das RowDeleted Ereignis danach ausgelöst wird. Erstellen Sie Ereignishandler für diese beiden Ereignisse mithilfe des folgenden Codes:

' A page variable to "remember" the deleted category's BrochurePath value
Private deletedCategorysPdfPath As String = Nothing
Protected Sub Categories_RowDeleting(sender As Object, e As GridViewDeleteEventArgs) _
    Handles Categories.RowDeleting
    
    ' Determine the PDF path for the category being deleted...
    Dim categoryID As Integer = Convert.ToInt32(e.Keys("CategoryID"))
    Dim categoryAPI As New CategoriesBLL()
    Dim categoriesData As Northwind.CategoriesDataTable = _
        categoryAPI.GetCategoryByCategoryID(categoryID)
    Dim category As Northwind.CategoriesRow = categoriesData(0)
    If category.IsBrochurePathNull() Then
        deletedCategorysPdfPath = Nothing
    Else
        deletedCategorysPdfPath = category.BrochurePath
    End If
End Sub
Protected Sub Categories_RowDeleted(sender As Object, e As GridViewDeletedEventArgs) _
    Handles Categories.RowDeleted
    
    ' Delete the brochure file if there were no problems deleting the record
    If e.Exception Is Nothing Then
        DeleteRememberedBrochurePath()
    End If
End Sub

RowDeleting Im Ereignishandler wird die CategoryID gelöschte Zeile aus der GridView-Auflistung DataKeys abgerufen, auf die in diesem Ereignishandler über die e.Keys Auflistung zugegriffen werden kann. Als Nächstes wird die Klasse CategoriesBLL aufgerufen, um Informationen zum zu löschenden Datensatz zurückzugeben. Wenn das zurückgegebene CategoriesDataRow Objekt einen Nicht-WertNULL``BrochurePath aufweist, wird es in der Seitenvariablen deletedCategorysPdfPath gespeichert, sodass die Datei im RowDeleted Ereignishandler gelöscht werden kann.

Hinweis

Anstatt die BrochurePath Details für den Datensatz abzurufen, der im CategoriesRowDeletingEreignishandler gelöscht wird, hätten wir alternativ das BrochurePath zur DataKeyNames-Eigenschaft des GridView hinzufügen und über die e.Keys-Sammlung auf den Wert des Datensatzes zugreifen können. Dies würde die Größe des Ansichtszustands von GridView leicht erhöhen, jedoch den benötigten Code reduzieren und eine Datenbankabfrage einsparen.

Nachdem der zugrunde liegende Löschbefehl objectDataSource aufgerufen wurde, wird der GridView-Ereignishandler RowDeleted ausgelöst. Wenn es beim Löschen der Daten keine Ausnahmen gibt und ein Wert für deletedCategorysPdfPath vorhanden ist, wird die PDF-Datei aus dem Dateisystem gelöscht. Beachten Sie, dass dieser zusätzliche Code nicht erforderlich ist, um die Binärdaten der Kategorie zu bereinigen, die mit dem Bild verknüpft sind. Das liegt daran, dass die Bilddaten direkt in der Datenbank gespeichert werden, sodass beim Löschen der Categories Zeile auch die Bilddaten der Kategorie gelöscht werden.

Führen Sie nach dem Hinzufügen der beiden Ereignishandler diesen Testfall erneut aus. Beim Löschen der Kategorie wird auch die zugehörige PDF-Datei gelöscht.

Das Aktualisieren der Binärdaten, die mit einem bestehenden Datensatz verknüpft sind, bietet einige interessante Herausforderungen. Der Rest dieses Lernprogramms befasst sich mit dem Hinzufügen von Updatefunktionen zu der Broschüre und dem Bild. In Schritt 6 werden Techniken zum Aktualisieren der Broschüreninformationen untersucht, während Schritt 7 das Aktualisieren des Bilds untersucht.

Schritt 6: Aktualisieren einer Kategorie-Broschüre

Wie im Lernprogramm "Ein Überblick über das Einfügen, Aktualisieren und Löschen von Daten" beschrieben, bietet das GridView integrierte Bearbeitungsunterstützung auf Zeilenebene, die durch das Anklicken eines Kontrollkästchens implementiert werden kann, wenn die zugrunde liegende Datenquelle entsprechend konfiguriert ist. Derzeit ist ObjectDataSource noch nicht so konfiguriert, CategoriesDataSource dass die Aktualisierungsunterstützung eingeschlossen wird, also fügen wir dies hinzu.

Klicken Sie im Assistenten "ObjectDataSource" auf den Link "Datenquelle konfigurieren", und fahren Sie mit dem zweiten Schritt fort. Aufgrund der DataObjectMethodAttribute Verwendung in CategoriesBLL sollte die UPDATE-Dropdownliste automatisch mit der Überladung gefüllt werden, die UpdateCategory vier Eingabeparameter akzeptiert (für alle Spalten außer Picture). Ändern Sie dies so, dass es die Überladung mit fünf Parametern verwendet.

Konfigurieren der ObjectDataSource für die Verwendung der UpdateCategory-Methode, die einen Parameter für Bild enthält

Abbildung 9: Konfigurieren Sie die ObjectDataSource, um die Methode UpdateCategory zu verwenden, die einen Parameter für Picture enthält (Klicken, um das Bild in voller Größe anzuzeigen)

Die ObjectDataSource enthält nun einen Wert für ihre UpdateMethod Eigenschaft sowie entsprechende UpdateParameter Werte. Wie in Schritt 4 erwähnt, legt Visual Studio die ObjectDataSource s-Eigenschaft OldValuesParameterFormatString bei Verwendung des Assistenten zum Konfigurieren der Datenquelle auf original_{0} fest. Dies führt zu Problemen mit den Aktualisierungs- und Löschmethodenaufrufen. Löschen Sie daher entweder diese Eigenschaft vollständig, oder setzen Sie sie auf die Standardeinstellung zurück. {0}

Nach Abschluss des Assistenten und Behebung des OldValuesParameterFormatString sollte das deklarative Markup von ObjectDataSource wie folgt aussehen:

<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="{0}" SelectMethod="GetCategories" 
    TypeName="CategoriesBLL" InsertMethod="InsertWithPicture" 
    DeleteMethod="DeleteCategory" UpdateMethod="UpdateCategory">
    <InsertParameters>
        <asp:Parameter Name="categoryName" Type="String" />
        <asp:Parameter Name="description" Type="String" />
        <asp:Parameter Name="brochurePath" Type="String" />
        <asp:Parameter Name="picture" Type="Object" />
    </InsertParameters>
    <DeleteParameters>
        <asp:Parameter Name="categoryID" Type="Int32" />
    </DeleteParameters>
    <UpdateParameters>
        <asp:Parameter Name="categoryName" Type="String" />
        <asp:Parameter Name="description" Type="String" />
        <asp:Parameter Name="brochurePath" Type="String" />
        <asp:Parameter Name="picture" Type="Object" />
        <asp:Parameter Name="categoryID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Um die integrierten Bearbeitungsfeatures von GridView zu aktivieren, wählen Sie die Option "Bearbeitung aktivieren" im Smarttag "GridView". Dadurch wird die CommandField-Eigenschaft ShowEditButton auf Truefestgelegt, wodurch eine Schaltfläche "Bearbeiten" (und "Aktualisieren" und "Abbrechen") für die bearbeitete Zeile hinzukommt.

Konfigurieren der GridView zur Unterstützung der Bearbeitung

Abbildung 10: Konfigurieren der GridView zur Unterstützung der Bearbeitung (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Besuchen Sie die Seite in einem Browser und klicken Sie auf eine der Bearbeitungsschaltflächen der jeweiligen Zeile. Die CategoryName- und Description-BoundFields werden als Eingabefelder gerendert. Das BrochurePath TemplateField hat kein EditItemTemplate, daher wird weiterhin ein Link zur Broschüre ItemTemplate angezeigt. Das Picture ImageField wird als TextBox gerendert, dessen Text Eigenschaft dem Wert des ImageField DataImageUrlField zugewiesen ist, in diesem Fall CategoryID.

GridView fehlt eine Bearbeitungsschnittstelle für BroschürePath

Abbildung 11: Die GridView verfügt nicht über BrochurePath eine Bearbeitungsschnittstelle (Klick, um das Bild in voller Größe anzuzeigen)

Anpassen derBrochurePathBearbeitungsschnittstelle

Wir müssen eine Bearbeitungsschnittstelle für das BrochurePath TemplateField erstellen, die dem Benutzer eine der folgenden Möglichkeiten ermöglicht:

  • Lassen Sie die Broschüre der Kategorie as-iszurück
  • Aktualisieren sie die Broschüre der Kategorie, indem Sie eine neue Broschüre hochladen oder
  • Entfernen Sie die Broschüre der Kategorie vollständig (falls die Kategorie nicht mehr über eine zugehörige Broschüre verfügt).

Außerdem müssen wir die Bearbeitungsschnittstelle von Picture ImageField aktualisieren, dies wird jedoch in Schritt 7 beschrieben.

Klicken Sie im Smarttag "GridView" auf den Link "Vorlagen bearbeiten", und wählen Sie in der Dropdownliste die BrochurePath Vorlagenfelder EditItemTemplate aus. Fügen Sie dieser Vorlage ein RadioButtonList-Websteuerelement hinzu, und legen Sie dessen ID Eigenschaft auf BrochureOptions und deren AutoPostBack Eigenschaft auf True. Klicken Sie im Eigenschaftenfenster auf die Auslassungspunkte in der Items Eigenschaft, wodurch der ListItem Sammlungs-Editor angezeigt wird. Fügen Sie die folgenden drei Optionen mit Value 1, 2 und 3 hinzu:

  • Aktuelle Broschüre verwenden
  • Aktuelle Broschüre entfernen
  • Neue Broschüre hochladen

Legen Sie die erste ListItem s-Eigenschaft Selected auf True.

Hinzufügen von drei ListItems zur RadioButtonList

Abbildung 12: Hinzufügen von drei ListItem s zur RadioButtonList

Fügen Sie unter der RadioButtonList ein FileUpload-Steuerelement mit dem Namen hinzu BrochureUpload. Legen Sie die zugehörige Visible-Eigenschaft auf False fest.

Hinzufügen eines RadioButtonList- und FileUpload-Steuerelements zur EditItemTemplate

Abbildung 13: Hinzufügen eines RadioButtonList- und FileUpload-Steuerelements zum EditItemTemplate (Klicken, um das Bild in voller Größe anzuzeigen)

Dieses RadioButtonList bietet die drei Optionen für den Benutzer. Die Idee besteht darin, dass das FileUpload-Steuerelement nur angezeigt wird, wenn die letzte Option ,Neue Broschüre hochladen' ausgewählt ist. Erstellen Sie dazu einen Ereignishandler für das RadioButtonList-Ereignis SelectedIndexChanged , und fügen Sie den folgenden Code hinzu:

Protected Sub BrochureOptions_SelectedIndexChanged _
    (sender As Object, e As EventArgs)
    
    ' Get a reference to the RadioButtonList and its Parent
    Dim BrochureOptions As RadioButtonList = _
        CType(sender, RadioButtonList)
    Dim parent As Control = BrochureOptions.Parent
    ' Now use FindControl("controlID") to get a reference of the 
    ' FileUpload control
    Dim BrochureUpload As FileUpload = _
        CType(parent.FindControl("BrochureUpload"), FileUpload)
    ' Only show BrochureUpload if SelectedValue = "3"
    BrochureUpload.Visible = (BrochureOptions.SelectedValue = "3")
End Sub

Da sich die RadioButtonList- und FileUpload-Steuerelemente in einer Vorlage befinden, müssen wir ein wenig Code schreiben, um programmgesteuert auf diese Steuerelemente zuzugreifen. Dem SelectedIndexChanged-Ereignishandler wird im sender-Eingabeparameter ein Verweis auf die RadioButtonList übergeben. Um das FileUpload-Steuerelement abzurufen, müssen wir das übergeordnete RadioButtonList-Steuerelement abrufen und die FindControl("controlID") Methode von dort aus verwenden. Sobald ein Verweis auf die Steuerelemente "RadioButtonList" und "FileUpload" vorhanden ist, wird die Eigenschaft des FileUpload-Steuerelements Visible nur dann auf True festgelegt, wenn "RadioButtonList" SelectedValue gleich 3 ist, was die Option für das Hochladen der neuen Broschüre Value ist.

Nehmen Sie sich mit diesem Code einen Moment Zeit, um die Bearbeitungsschnittstelle zu testen. Klicken Sie auf die Schaltfläche "Bearbeiten" für eine Zeile. Zunächst sollte die Option "Aktuelle Broschüre verwenden" ausgewählt werden. Durch das Ändern des ausgewählten Indexes kommt es zu einem Postback. Wenn die dritte Option ausgewählt ist, wird das FileUpload-Steuerelement angezeigt, andernfalls wird es ausgeblendet. Abbildung 14 zeigt die Bearbeitungsoberfläche, wenn zuerst auf die Schaltfläche "Bearbeiten" geklickt wird. Abbildung 15 zeigt die Schnittstelle, nachdem die Option "Neue Broschüre hochladen" ausgewählt wurde.

Zunächst ist die Option

Abbildung 14: Anfänglich ist die Option "Aktuelle Broschüre verwenden" ausgewählt (Zum Anzeigen des Bilds mit voller Größe klicken)

Wenn Sie die Option

Abbildung 15: Auswählen der Option "Neue Broschüre hochladen" zeigt das FileUpload-Steuerelement an (Klicken, um das Bild in voller Größe anzuzeigen)

Speichern der Broschürendatei und Aktualisieren derBrochurePathSpalte

Wenn auf die Schaltfläche "GridView s Update" geklickt wird, wird das RowUpdating Ereignis ausgelöst. Der Updatebefehl von ObjectDataSource wird aufgerufen, und das GridView-Ereignis RowUpdated wird ausgelöst. Wie beim Löschen des Workflows müssen wir Ereignishandler für beide Ereignisse erstellen. Im RowUpdating Ereignishandler müssen wir bestimmen, welche Aktion auf der Grundlage der SelectedValue des BrochureOptions RadioButtonList ausgeführt werden soll.

  • Wenn dies SelectedValue 1 ist, möchten wir dieselbe BrochurePath Einstellung beibehalten. Daher müssen wir den Parameter ObjectDataSource brochurePath auf den vorhandenen BrochurePath Wert des Datensatzes festlegen, der aktualisiert wird. Der Parameter von ObjectDataSource's brochurePath kann mithilfe von e.NewValues["brochurePath"] = value gesetzt werden.
  • Wenn SelectedValue gleich 2 ist, wollen wir den Wert des Datensatzes BrochurePath auf NULL setzen. Dies kann erreicht werden, indem Sie den Parameter ObjectDataSource brochurePath auf Nothingfestlegen, der dazu führt, dass eine Datenbank NULL in der UPDATE Anweisung verwendet wird. Wenn es eine vorhandene Broschürendatei gibt, die entfernt wird, müssen wir die vorhandene Datei löschen. Allerdings möchten wir dies nur tun, wenn das Update abgeschlossen ist, ohne eine Ausnahme auszuheben.
  • Wenn SelectedValue 3 ist, möchten wir sicherstellen, dass der Benutzer eine PDF-Datei hochgeladen hat, diese dann im Dateisystem speichert und den Spaltenwert des Datensatzes BrochurePath aktualisiert. Darüber hinaus müssen wir die vorherige Datei löschen, wenn eine vorhandene Broschürendatei ersetzt wird. Allerdings möchten wir dies nur tun, wenn das Update abgeschlossen ist, ohne eine Ausnahme auszuheben.

Die erforderlichen Schritte, die ausgeführt werden müssen, wenn die RadioButtonList s SelectedValue 3 ist, sind praktisch identisch mit denen, die vom DetailsView s-Ereignishandler ItemInserting verwendet werden. Dieser Ereignishandler wird ausgeführt, wenn ein neuer Kategoriedatensatz aus dem DetailsView-Steuerelement hinzugefügt wird, das wir im vorherigen Lernprogramm hinzugefügt haben. Daher müssen wir diese Funktionalität in separate Methoden umgestalten. Insbesondere habe ich die übliche Funktionalität in zwei Methoden ausgelagert.

  • ProcessBrochureUpload(FileUpload, out bool) akzeptiert als Eingabe eine FileUpload-Steuerelementinstanz und einen booleschen Ausgabewert, der angibt, ob der Lösch- oder Bearbeitungsvorgang fortgesetzt werden soll oder ob er aufgrund eines Überprüfungsfehlers abgebrochen werden soll. Diese Methode gibt den Pfad zur gespeicherten Datei zurück oder null wenn keine Datei gespeichert wurde.
  • DeleteRememberedBrochurePath löscht die Datei, die in der Seitenvariable deletedCategorysPdfPath durch den Pfad angegeben wird, wenn deletedCategorysPdfPath nicht null ist.

Der Code für diese beiden Methoden folgt. Beachten Sie die Ähnlichkeit zwischen ProcessBrochureUpload und dem DetailsView s-Ereignishandler ItemInserting aus dem vorherigen Lernprogramm. In diesem Lernprogramm habe ich die Ereignishandler von DetailsView aktualisiert, um diese neuen Methoden zu verwenden. Laden Sie den Code herunter, der diesem Lernprogramm zugeordnet ist, um die Änderungen an den DetailsView-Ereignishandlern anzuzeigen.

Private Function ProcessBrochureUpload _
    (BrochureUpload As FileUpload, CancelOperation As Boolean) As String
    
    CancelOperation = False    ' by default, do not cancel operation
    If BrochureUpload.HasFile Then
        ' Make sure that a PDF has been uploaded
        If String.Compare(System.IO.Path.GetExtension(BrochureUpload.FileName), _
            ".pdf", True) <> 0 Then
            
            UploadWarning.Text = _
                "Only PDF documents may be used for a category's brochure."
            UploadWarning.Visible = True
            CancelOperation = True
            Return Nothing
        End If
        Const BrochureDirectory As String = "~/Brochures/"
        Dim brochurePath As String = BrochureDirectory + BrochureUpload.FileName
        Dim fileNameWithoutExtension As String = _
            System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName)
        Dim iteration As Integer = 1
        While System.IO.File.Exists(Server.MapPath(brochurePath))
            brochurePath = String.Concat(BrochureDirectory, _
                fileNameWithoutExtension, "-", iteration, ".pdf")
            iteration += 1
        End While
        ' Save the file to disk and set the value of the brochurePath parameter
        BrochureUpload.SaveAs(Server.MapPath(brochurePath))
        Return brochurePath
    Else
        ' No file uploaded
        Return Nothing
    End If
End Function
Private Sub DeleteRememberedBrochurePath()
    ' Is there a file to delete?
    If deletedCategorysPdfPath IsNot Nothing Then
        System.IO.File.Delete(Server.MapPath(deletedCategorysPdfPath))
    End If
End Sub

Die GridView-Ereignishandler RowUpdating und RowUpdated verwenden die Methoden ProcessBrochureUpload und DeleteRememberedBrochurePath, wie der folgende Code zeigt.

Protected Sub Categories_RowUpdating _
    (sender As Object, e As GridViewUpdateEventArgs) _
    Handles Categories.RowUpdating
    
    ' Reference the RadioButtonList
    Dim BrochureOptions As RadioButtonList = _
        CType(Categories.Rows(e.RowIndex).FindControl("BrochureOptions"), _
            RadioButtonList)
    ' Get BrochurePath information about the record being updated
    Dim categoryID As Integer = Convert.ToInt32(e.Keys("CategoryID"))
    Dim categoryAPI As New CategoriesBLL()
    Dim categoriesData As Northwind.CategoriesDataTable = _
        categoryAPI.GetCategoryByCategoryID(categoryID)
    Dim category As Northwind.CategoriesRow = categoriesData(0)
    If BrochureOptions.SelectedValue = "1" Then
        ' Use current value for BrochurePath
        If category.IsBrochurePathNull() Then
            e.NewValues("brochurePath") = Nothing
        Else
            e.NewValues("brochurePath") = category.BrochurePath
        End If
    ElseIf BrochureOptions.SelectedValue = "2" Then
        ' Remove the current brochure (set it to NULL in the database)
        e.NewValues("brochurePath") = Nothing
    ElseIf BrochureOptions.SelectedValue = "3" Then
        ' Reference the BrochurePath FileUpload control
        Dim BrochureUpload As FileUpload = _
            CType(categories.Rows(e.RowIndex).FindControl("BrochureUpload"), _
                FileUpload)
        ' Process the BrochureUpload
        Dim cancelOperation As Boolean = False
        e.NewValues("brochurePath") = _
            ProcessBrochureUpload(BrochureUpload, cancelOperation)
        e.Cancel = cancelOperation
    Else
        ' Unknown value!
        Throw New ApplicationException( _
            String.Format("Invalid BrochureOptions value, {0}", _
                BrochureOptions.SelectedValue))
    End If
    If BrochureOptions.SelectedValue = "2" OrElse _
        BrochureOptions.SelectedValue = "3" Then
        
        ' "Remember" that we need to delete the old PDF file
        If (category.IsBrochurePathNull()) Then
            deletedCategorysPdfPath = Nothing
        Else
            deletedCategorysPdfPath = category.BrochurePath
        End If
    End If
End Sub
Protected Sub Categories_RowUpdated _
    (sender As Object, e As GridViewUpdatedEventArgs) _
    Handles Categories.RowUpdated
    
    ' If there were no problems and we updated the PDF file, 
    ' then delete the existing one
    If e.Exception Is Nothing Then
        DeleteRememberedBrochurePath()
    End If
End Sub

Beachten Sie, dass der RowUpdating Ereignishandler eine Reihe bedingter Anweisungen verwendet, um die entsprechende Aktion basierend auf dem BrochureOptions Eigenschaftswert "RadioButtonList" SelectedValue auszuführen.

Mit diesem Code können Sie eine Kategorie bearbeiten und die aktuelle Broschüre verwenden, keine Broschüre verwenden oder eine neue hochladen. Fahren Sie fort, und probieren Sie es aus. Legen Sie Haltepunkte in den RowUpdating Und RowUpdated Ereignishandlern fest, um einen Eindruck vom Workflow zu erhalten.

Schritt 7: Hochladen eines neuen Bilds

Die Picture Bildfeld-Bearbeitungsschnittstelle wird als Textfeld gerendert, das mit dem Wert aus seiner DataImageUrlField Eigenschaft aufgefüllt wird. Während des Bearbeitungsworkflows übergibt GridView einen Parameter an die ObjectDataSource. Der Name des Parameters ist der Wert der ImageField-Eigenschaft DataImageUrlField, und der Wert des Parameters ist der im Textfeld der Bearbeitungsschnittstelle eingegebene Wert. Dieses Verhalten eignet sich, wenn das Bild als Datei im Dateisystem gespeichert wird und die DataImageUrlField vollständige URL des Bilds enthält. Unter solchen Umständen zeigt die Bearbeitungsoberfläche die URL des Bilds im Textfeld an, die der Benutzer ändern und wieder in der Datenbank gespeichert haben kann. Zugegeben, diese Standardschnittstelle erlaubt es dem Benutzer nicht, ein neues Bild hochzuladen, aber sie können die URL des Bildes vom aktuellen Wert zu einem anderen ändern. Für dieses Tutorial reicht die standardmäßige Bearbeitungsschnittstelle von ImageField jedoch nicht aus, da die Picture Binärdaten direkt in der Datenbank gespeichert werden und die DataImageUrlField Eigenschaft nur die CategoryID.

Um besser zu verstehen, was in unserem Lernprogramm passiert, wenn ein Benutzer eine Zeile mit einem ImageField bearbeitet, betrachten Sie das folgende Beispiel: Ein Benutzer bearbeitet eine Zeile mit CategoryID 10, wodurch das Picture ImageField als Textfeld mit dem Wert 10 gerendert wird. Stellen Sie sich vor, dass der Benutzer den Wert in diesem Textfeld in 50 ändert und auf die Schaltfläche "Aktualisieren" klickt. Ein Postback tritt auf, und GridView erstellt zunächst einen Parameter mit dem Wert 50 und dem Namen CategoryID. Bevor das GridView diesen Parameter (sowie die CategoryName- und Description-Parameter) sendet, fügt es die Werte aus der DataKeys-Auflistung hinzu. Daher überschreibt er den CategoryID Parameter mit dem zugrunde liegenden CategoryID Wert 10 der aktuellen Zeile. Kurz gesagt hat die Bearbeitungsschnittstelle von ImageField keine Auswirkungen auf den Bearbeitungsworkflow für dieses Lernprogramm, da die Namen der ImageField-Eigenschaft DataImageUrlField und der Rasterwert DataKey eins in demselben sind.

Während das ImageField das Anzeigen eines Bilds auf der Grundlage von Datenbankdaten erleichtert, möchten wir kein Textfeld in der Bearbeitungsoberfläche bereitstellen. Stattdessen möchten wir ein FileUpload-Steuerelement anbieten, das der Endbenutzer verwenden kann, um das Bild der Kategorie zu ändern. Im Gegensatz zum BrochurePath-Wert haben wir uns bei diesen Lernprogrammen entschieden, dass jede Kategorie ein Bild aufweisen muss. Daher müssen wir nicht zulassen, dass der Benutzer darauf hinweist, dass es kein zugeordnetes Bild gibt; stattdessen kann der Benutzer entweder ein neues Bild hochladen oder das bestehende Bild as-isbelassen.

Um die Bearbeitungsschnittstelle von ImageField anzupassen, müssen wir sie in ein TemplateField konvertieren. Klicken Sie im Smarttag "GridView" auf den Link "Spalten bearbeiten", wählen Sie das ImageField aus, und klicken Sie auf den Link, um dieses Feld in ein TemplateField zu konvertieren.

Konvertieren des ImageFields in ein TemplateField

Abbildung 16: Konvertieren des ImageFields in ein TemplateField

Wenn Sie imageField auf diese Weise in ein TemplateField konvertieren, wird ein TemplateField mit zwei Vorlagen generiert. Wie die folgende deklarative Syntax zeigt, enthält das ItemTemplate Bildwebsteuerelement, dessen ImageUrl Eigenschaft mithilfe der Datenbindungssyntax basierend auf ImageField s DataImageUrlField und DataImageUrlFormatString Eigenschaften zugewiesen wird. Das EditItemTemplate Enthält ein TextBox-Objekt, dessen Text Eigenschaft an den durch die DataImageUrlField Eigenschaft angegebenen Wert gebunden ist.

<asp:TemplateField>
    <EditItemTemplate>
        <asp:TextBox ID="TextBox1" runat="server" 
            Text='<%# Eval("CategoryID") %>'></asp:TextBox>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Image ID="Image1" runat="server" 
            ImageUrl='<%# Eval("CategoryID", 
                "DisplayCategoryPicture.aspx?CategoryID={0}") %>' />
    </ItemTemplate>
</asp:TemplateField>

Wir müssen die EditItemTemplate Datei aktualisieren, um ein FileUpload-Steuerelement zu verwenden. Klicken Sie im Smarttag "GridView" auf den Link "Vorlagen bearbeiten", und wählen Sie dann in der Dropdownliste die Picture Vorlagenfelder EditItemTemplate aus. In der Vorlage sollten Sie ein Textfeld sehen – entfernen Sie dieses. Ziehen Sie als Nächstes ein FileUpload-Steuerelement aus der Toolbox in das Template und setzen Sie sein ID auf PictureUpload. Fügen Sie den Text "Um das Bild der Kategorie zu ändern, geben Sie ein neues Bild an" hinzu. Wenn Sie das Bild der Kategorie unverändert beibehalten möchten, lassen Sie das Feld auch für die Vorlage leer.

Hinzufügen eines FileUpload-Steuerelements zur EditItemTemplate

Abbildung 17: Einfügen eines FileUpload-Steuerelements in EditItemTemplate (Klicken, um das Bild in voller Größe anzuzeigen)

Nachdem Sie die Bearbeitungsoberfläche angepasst haben, zeigen Sie ihren Fortschritt in einem Browser an. Beim Anzeigen einer Zeile im schreibgeschützten Modus wird das Bild der Kategorie wie zuvor angezeigt. Wenn jedoch auf die Schaltfläche "Bearbeiten" geklickt wird, wird die Bildspalte als Text mit einem FileUpload-Steuerelement dargestellt.

Die Bearbeitungsschnittstelle enthält ein FileUpload-Steuerelement

Abbildung 18: Die Bearbeitungsschnittstelle enthält ein FileUpload-Steuerelement (Klicken, um das Bild in voller Größe anzuzeigen)

Denken Sie daran, dass die ObjectDataSource so konfiguriert ist, dass die Methode der Klasse CategoriesBLL aufgerufen wird, die die Binärdaten für das Bild als UpdateCategory Array als Eingabe akzeptiert. Wenn dieses Array jedoch Nothing ist, wird die alternative Überladung UpdateCategory aufgerufen, die die UPDATE SQL-Anweisung ausgibt, die die Picture Spalte nicht ändert, wodurch das derzeitige Bild der Kategorie intakt bleibt. Daher müssen wir im GridView-Ereignishandler RowUpdating programmgesteuert auf das PictureUpload FileUpload-Steuerelement verweisen und ermitteln, ob eine Datei hochgeladen wurde. Wenn eine nicht hochgeladen wurde, möchten wir keinen Wert für den picture Parameter angeben. Wenn eine Datei dagegen im PictureUpload FileUpload-Steuerelement hochgeladen wurde, möchten wir sicherstellen, dass es sich um eine JPG-Datei handelt. Wenn dies der Grund ist, können wir den binären Inhalt über den picture Parameter an die ObjectDataSource senden.

Wie bei dem code, der in Schritt 6 verwendet wird, ist bereits ein Großteil des hier benötigten Codes im DetailsView-Ereignishandler ItemInserting vorhanden. Daher habe ich die allgemeine Funktionalität in eine neue Methode umgestaltet und den ValidPictureUpload Ereignishandler so aktualisiert, ItemInsertingdass diese Methode verwendet wird.

Fügen Sie den folgenden Code am Anfang des GridView-Ereignishandlers RowUpdating hinzu. Es ist wichtig, dass dieser Code vor dem Code steht, der die Broschürendatei speichert, da wir die Broschüre nicht im Dateisystem des Webservers speichern möchten, wenn eine ungültige Bilddatei hochgeladen wird.

' Reference the PictureUpload FileUpload
Dim PictureUpload As FileUpload = _
    CType(categories.Rows(e.RowIndex).FindControl("PictureUpload"), _
        FileUpload)
If PictureUpload.HasFile Then
    ' Make sure the picture upload is valid
    If ValidPictureUpload(PictureUpload) Then
        e.NewValues("picture") = PictureUpload.FileBytes
    Else
        ' Invalid file upload, cancel update and exit event handler
        e.Cancel = True
        Exit Sub
    End If
End If

Die ValidPictureUpload(FileUpload) Methode verwendet ein FileUpload-Steuerelement als einzigen Eingabeparameter und überprüft die Erweiterung der hochgeladenen Datei, um sicherzustellen, dass die hochgeladene Datei ein JPG ist. Sie wird nur aufgerufen, wenn eine Bilddatei hochgeladen wird. Wenn keine Datei hochgeladen wird, wird der Bildparameter nicht festgelegt und verwendet daher den Standardwert von Nothing. Wenn ein Bild hochgeladen wird und ValidPictureUploadTrue zurückgibt, wird dem Parameter picture die Binärdaten des hochgeladenen Bildes zugewiesen. Wenn die Methode False zurückgibt, wird der Update-Workflow abgebrochen und der Ereignishandler beendet.

Der ValidPictureUpload(FileUpload) Methodencode, der aus dem DetailsView-Ereignishandler ItemInserting umgestaltet wurde, folgt:

Private Function ValidPictureUpload(ByVal PictureUpload As FileUpload) As Boolean
    ' Make sure that a JPG has been uploaded
    If String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), _
        ".jpg", True) <> 0 AndAlso _
        String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), _
        ".jpeg", True) <> 0 Then
        
        UploadWarning.Text = _
            "Only JPG documents may be used for a category's picture."
        UploadWarning.Visible = True
        Return False
    Else
        Return True
    End If
End Function

Schritt 8: Ersetzen der ursprünglichen Kategorienbilder durch JPGs

Denken Sie daran, dass die ursprünglichen acht Kategorien Bilder Bitmapdateien sind, die in eine OLE-Kopfzeile eingeschlossen sind. Nachdem wir nun die Möglichkeit hinzugefügt haben, das Bild eines vorhandenen Datensatzes zu bearbeiten, nehmen Sie sich einen Moment, um diese Bitmap-Bilder durch JPG-Dateien zu ersetzen. Wenn Sie die aktuellen Kategoriebilder weiterhin verwenden möchten, können Sie sie in JPGs konvertieren, indem Sie die folgenden Schritte ausführen:

  1. Speichern Sie die Bitmapbilder auf Ihrer Festplatte. Besuchen Sie die UpdatingAndDeleting.aspx Seite in Ihrem Browser und klicken Sie für jede der ersten acht Kategorien mit der rechten Maustaste auf das Bild und wählen Sie 'Bild speichern'.
  2. Öffnen Sie das Bild in Ihrem Gewünschten Bild-Editor. Sie können beispielsweise Microsoft Paint verwenden.
  3. Speichern Sie die Bitmap als JPG-Bild.
  4. Aktualisieren Sie das Bild der Kategorie über die Bearbeitungsoberfläche mithilfe der JPG-Datei.

Nach dem Bearbeiten einer Kategorie und dem Hochladen des JPG-Bilds wird das Bild nicht im Browser gerendert, da die DisplayCategoryPicture.aspx Seite die ersten 78 Bytes aus den Bildern der ersten acht Kategorien entfernt. Beheben Sie dies, indem Sie den Code entfernen, der das Entfernen der OLE-Header durchführt. Danach sollte der DisplayCategoryPicture.aspx``Page_Load Ereignishandler nur den folgenden Code aufweisen:

Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    Dim categoryID As Integer = _
        Convert.ToInt32(Request.QueryString("CategoryID"))
    ' Get information about the specified category
    Dim categoryAPI As New CategoriesBLL()
    Dim categories As Northwind.CategoriesDataTable = _
        categoryAPI.GetCategoryWithBinaryDataByCategoryID(categoryID)
    Dim category As Northwind.CategoriesRow = categories(0)
    ' For new categories, images are JPGs...
    ' Output HTTP headers providing information about the binary data
    Response.ContentType = "image/jpeg"
    ' Output the binary data
    Response.BinaryWrite(category.Picture)
End Sub

Hinweis

Die Einfügungs- und Bearbeitungsschnittstellen der UpdatingAndDeleting.aspx Seite könnten etwas mehr Überarbeitung vertragen. Die BoundFields in der DetailsView und GridView sollen in TemplateFields umgewandelt werden. Da CategoryName keine Werte zulässig sind NULL , sollte ein RequiredFieldValidator hinzugefügt werden. Und das Description TextBox-Objekt sollte wahrscheinlich in ein mehrzeiliges TextBox-Objekt konvertiert werden. Ich überlasse dir diese letzten Feinheiten als Übung.

Zusammenfassung

In diesem Lernprogramm schließen wir unsere Betrachtung der Arbeit mit Binärdaten ab. In diesem Lernprogramm und den vorherigen drei Haben wir gesehen, wie Binärdaten im Dateisystem oder direkt in der Datenbank gespeichert werden können. Ein Benutzer stellt dem System Binärdaten bereit, indem er eine Datei von seiner Festplatte aus auswählt und auf den Webserver hochlädt, wo sie im Dateisystem gespeichert oder in die Datenbank eingefügt werden kann. ASP.NET 2.0 enthält ein Steuerelement zum Hochladen von Dateien, das die Bereitstellung einer solchen Schnittstelle so einfach wie das Ziehen und Ablegen macht. Wie im Lernprogramm zum Hochladen von Dateien erwähnt, eignet sich das FileUpload-Steuerelement jedoch nur für relativ kleine Dateiuploads, idealerweise nicht über ein Megabyte. Darüber hinaus haben wir untersucht, wie hochgeladene Daten mit dem zugrunde liegenden Datenmodell verknüpft werden, sowie wie die Binärdaten aus vorhandenen Datensätzen bearbeitet und gelöscht werden.

In unseren nächsten Lernprogrammen werden verschiedene Caching-Techniken untersucht. Das Zwischenspeichern bietet eine Möglichkeit, die Gesamtleistung einer Anwendung zu verbessern, indem die Ergebnisse aus teuren Vorgängen gespeichert werden, sodass auf sie schneller zugegriffen werden kann.

Glückliche Programmierung!

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann bei mitchell@4GuysFromRolla.comerreicht werden.

Besonderer Dank an

Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitender Prüfer für dieses Lernprogramm war Teresa Murphy. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.