Sdílet prostřednictvím


Aktualizace a odstranění stávajících binárních dat (VB)

Scott Mitchell

Stáhnout PDF

V předchozích kurzech jsme viděli, jak ovládací prvek GridView usnadňuje úpravy a odstraňování textových dat. V tomto kurzu vidíme, jak GridView ovládací prvek také umožňuje upravovat a odstraňovat binární data, ať už jsou binární data uložena v databázi nebo uložena v systému souborů.

Úvod

V posledních třech kurzech jsme přidali poměrně hodně funkcí pro práci s binárními daty. Začali jsme přidáním BrochurePath sloupce do Categories tabulky a odpovídajícím způsobem jsme aktualizovali architekturu. Přidali jsme také metody Vrstva přístupu k datům a Vrstva obchodní logiky pro práci s existujícím Picture sloupcem tabulky Categories, který obsahuje binární obsah souboru obrázku. Vytvořili jsme webové stránky k prezentaci binárních dat v GridView odkaz ke stažení brožury, s obrázkem kategorie zobrazeným v <img> prvku a přidali DetailsView, aby uživatelé mohli přidat novou kategorii a nahrát její brožuru a obrazová data.

Jediné, co zbývá implementovat, je možnost upravovat a odstraňovat existující kategorie, což provedeme v tomto kurzu pomocí integrovaných funkcí pro úpravy a odstraňování GridView. Při úpravách kategorie bude uživatel moct volitelně nahrát nový obrázek nebo nechat kategorii dál používat existující obrázek. U brožury se můžou rozhodnout buď použít stávající brožuru, nahrát novou brožuru nebo označit, že kategorie už nemá přidruženou brožuru. Pusťme se do toho!

Krok 1: Aktualizace vrstvy přístupu k datům

Dal obsahuje automaticky generované Insertmetody , Updatea Delete , ale tyto metody byly generovány na základě hlavního CategoriesTableAdapter dotazu, který neobsahuje Picture sloupec. Insert Metody a Update proto neobsahují parametry pro určení binárních dat pro obrázek kategorie. Stejně jako v předchozím kurzu potřebujeme vytvořit novou metodu TableAdapter pro aktualizaci Categories tabulky při zadávání binárních dat.

Otevřete typed dataSet a v Designer klikněte pravým tlačítkem na CategoriesTableAdapter záhlaví s a v místní nabídce zvolte Přidat dotaz. Tím spustíte Průvodce konfigurací dotazu TableAdapter. Tento průvodce se začne ptát, jak by měl dotaz TableAdapter přistupovat k databázi. Zvolte Použít příkazy SQL a klikněte na Další. V dalším kroku se zobrazí výzva k vygenerování typu dotazu. Vzhledem k tomu, že vytváříme dotaz pro přidání nového záznamu Categories do tabulky, zvolte AKTUALIZOVAT a klikněte na Další.

Vyberte možnost AKTUALIZOVAT.

Obrázek 1: Výběr možnosti AKTUALIZOVAT (kliknutím zobrazíte obrázek v plné velikosti)

Teď musíme zadat UPDATE příkaz SQL. Průvodce automaticky navrhne UPDATE příkaz odpovídající hlavnímu dotazu TableAdapter (který aktualizuje CategoryNamehodnoty , Descriptiona BrochurePath ). Změňte příkaz tak, aby Picture se sloupec zahrnul spolu s parametrem @Picture , například takto:

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

Poslední obrazovka průvodce nás vyzve k pojmenování nové metody TableAdapter. Zadejte UpdateWithPicture a klikněte na Dokončit.

Pojmenujte novou metodu TableAdapter UpdateWithPicture.

Obrázek 2: Pojmenujte novou metodu UpdateWithPicture TableAdapter (kliknutím zobrazíte obrázek v plné velikosti)

Krok 2: Přidání metod vrstvy obchodní logiky

Kromě aktualizace dal potřebujeme aktualizovat BLL tak, aby zahrnovala metody pro aktualizaci a odstranění kategorie. Toto jsou metody, které budou vyvolány z prezentační vrstvy.

K odstranění kategorie můžeme použít automaticky vygenerovanou Delete metodu CategoriesTableAdapter s. Do třídy CategoriesBLL přidejte následující metodu:

<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

Pro účely tohoto kurzu vytvoříme dvě metody aktualizace kategorie – jednu, která očekává data binárního obrázku a vyvolá metodu UpdateWithPicture , kterou jsme právě přidali, CategoriesTableAdapter a druhou, která přijímá pouze CategoryNamehodnoty , Descriptiona BrochurePath a používá CategoriesTableAdapter automaticky vygenerovaný Update příkaz třídy s. Důvodem použití dvou metod je to, že za určitých okolností může uživatel chtít aktualizovat obrázek kategorie spolu s ostatními poli. V takovém případě bude uživatel muset nahrát nový obrázek. Nahraná data obrázku se pak dají použít v UPDATE příkazu . V jiných případech může uživatele zajímat jenom aktualizace názvu a popisu. Pokud UPDATE ale příkaz očekává i binární data pro Picture sloupec, pak bychom museli poskytnout i tyto informace. To by vyžadovalo další cestu do databáze, aby se data obrázku pro upravovaný záznam vrátila. Proto chceme dvě UPDATE metody. Vrstva obchodní logiky určí, kterou z nich použít, na základě toho, jestli jsou při aktualizaci kategorie k dispozici data obrázku.

Abyste to usnadnili, přidejte do CategoriesBLL třídy dvě metody, obě s názvem UpdateCategory. První z nich by měla jako vstupní parametry přijímat tři String s, Byte pole a a Integer druhá pouze tři String s a .Integer Vstupní String parametry jsou pro název kategorie, popis a cestu k souboru brožury, Byte pole je pro binární obsah obrázku kategorie a Integer určuje CategoryID záznam, který se má aktualizovat. Všimněte si, že první přetížení vyvolá druhé, pokud je Nothingpředané Byte pole :

<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

Krok 3: Kopírování funkce vložení a zobrazení

V předchozím kurzu jsme vytvořili stránku s názvem UploadInDetailsView.aspx , která obsahuje seznam všech kategorií v GridView a poskytli DetailsView pro přidání nových kategorií do systému. V tomto kurzu rozšíříme GridView tak, aby zahrnoval podporu úprav a odstraňování. Místo toho, abychom pokračovali v práci z UploadInDetailsView.aspxnástroje , pojďme místo toho umístit změny tohoto kurzu na UpdatingAndDeleting.aspx stránku ze stejné složky ~/BinaryData. Zkopírujte a vložte deklarativní kód a kód z do UploadInDetailsView.aspxUpdatingAndDeleting.aspx.

Začněte otevřením UploadInDetailsView.aspx stránky. Zkopírujte veškerou deklarativní syntaxi v elementu <asp:Content> , jak je znázorněno na obrázku 3. Dále otevřete UpdatingAndDeleting.aspx a vložte tento kód do jeho <asp:Content> elementu. Podobně zkopírujte kód z UploadInDetailsView.aspx třídy kódu na pozadí stránky do UpdatingAndDeleting.aspx.

Zkopírujte deklarativní kód z UploadInDetailsView.aspx

Obrázek 3: Zkopírování deklarativního kódu z UploadInDetailsView.aspx (kliknutím zobrazíte obrázek v plné velikosti)

Po zkopírování deklarativního kódu a kódu přejděte na adresu UpdatingAndDeleting.aspx. Měli byste vidět stejný výstup a měli byste mít stejné uživatelské prostředí jako UploadInDetailsView.aspx na stránce z předchozího kurzu.

Krok 4: Přidání podpory odstranění objektů ObjectDataSource a GridView

Jak jsme už probírali v kurzu Přehled vkládání, aktualizace a odstraňování dat , GridView poskytuje integrované možnosti odstraňování a tyto možnosti je možné povolit zaškrtnutím políčka, pokud podkladový zdroj dat mřížky podporuje odstranění. ObjectDataSource GridView je v současné době vázán (CategoriesDataSource) nepodporuje odstranění.

Pokud chcete tento problém napravit, klikněte na možnost Konfigurovat zdroj dat z inteligentní značky ObjectDataSource a spusťte průvodce. První obrazovka ukazuje, že ObjectDataSource je nakonfigurován pro práci s CategoriesBLL třídou . Klikněte na Další. V současné době jsou zadány pouze vlastnosti ObjectDataSource s InsertMethod a SelectMethod . Průvodce však automaticky vyplní rozevírací seznamy na kartách UPDATE a DELETE metodami UpdateCategory a DeleteCategory v uvedeném pořadí. Je to proto, že ve CategoriesBLL třídě jsme tyto metody označili DataObjectMethodAttribute pomocí jako výchozí metody pro aktualizaci a odstranění.

Prozatím nastavte rozevírací seznam AKTUALIZOVAT karty na (Žádné), ale rozevírací seznam ODSTRANIT karty nechte nastavený na DeleteCategory. K tomuto průvodci se vrátíme v kroku 6 a přidáme podporu aktualizací.

Nakonfigurujte ObjectDataSource tak, aby používal metodu DeleteCategory.

Obrázek 4: Konfigurace objektu ObjectDataSource pro použití DeleteCategory metody (kliknutím zobrazíte obrázek v plné velikosti)

Poznámka

Po dokončení průvodce se může Visual Studio zeptat, jestli chcete aktualizovat pole a klíče, čímž se pole webových ovládacích prvků dat znovu vygenerují. Zvolte Ne, protože pokud zvolíte Ano, přepíšete všechna přizpůsobení polí, která jste provedli.

ObjectDataSource teď bude obsahovat hodnotu pro svoji DeleteMethod vlastnost a také DeleteParameterhodnotu . Vzpomeňte si, že při použití průvodce k určení metod sada Visual Studio nastaví vlastnost ObjectDataSource na OldValuesParameterFormatStringoriginal_{0}, což způsobuje problémy s voláním metody update a odstranění. Proto buď tuto vlastnost úplně vymažte, {0}nebo ji resetujte na výchozí hodnotu . Pokud potřebujete aktualizovat paměť u této vlastnosti ObjectDataSource, přečtěte si kurz Přehled vkládání, aktualizace a odstraňování dat .

Po dokončení průvodce a opravě OldValuesParameterFormatStringby deklarativní kód ObjectDataSource měl vypadat podobně jako v následujícím příkladu:

<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>

Po konfiguraci ObjectDataSource přidejte do objektu GridView možnost odstranění zaškrtnutím políčka Povolit odstranění u inteligentní značky GridView. Tím přidáte CommandField do objektu GridView, jehož ShowDeleteButton vlastnost je nastavena na Truehodnotu .

Povolení podpory pro odstranění v zobrazení GridView

Obrázek 5: Povolení podpory pro odstranění v GridView (kliknutím zobrazíte obrázek v plné velikosti)

Chvíli si vyzkoušejte funkci odstranění. Mezi Products tabulkou s a CategoriesCategoryIDtabulkou CategoryID s existuje cizí klíč, takže pokud se pokusíte odstranit některou z prvních osmi kategorií, zobrazí se výjimka porušení omezení cizího klíče. Pokud chcete tuto funkci otestovat, přidejte novou kategorii poskytující brožuru i obrázek. Moje testovací kategorie zobrazená na obrázku 6 obsahuje soubor testovací brožury s názvem Test.pdf a testovací obrázek. Obrázek 7 ukazuje GridView po přidání testovací kategorie.

Přidání testovací kategorie s brožurou a obrázkem

Obrázek 6: Přidání testovací kategorie s brožurou a obrázkem (kliknutím zobrazíte obrázek v plné velikosti)

Po vložení testovací kategorie se zobrazí v zobrazení GridView.

Obrázek 7: Po vložení testovací kategorie se zobrazí v zobrazení GridView (kliknutím zobrazíte obrázek v plné velikosti).

V sadě Visual Studio aktualizujte Průzkumník řešení. Ve složce Test.pdf by se teď měl zobrazit nový soubor ~/Brochures (viz Obrázek 8).

Potom klikněte na odkaz Odstranit v řádku Testovací kategorie, což způsobí, že stránka bude postback a CategoriesBLL metoda třídy s DeleteCategory se aktivuje. Tím se vyvolá metoda DAL s Delete , což způsobí odeslání příslušného DELETE příkazu do databáze. Data se pak vrátí do objektu GridView a značky se odešlou zpět do klienta s již neexistující testovací kategorií.

Přestože pracovní postup odstranění úspěšně odebral záznam testovací kategorie z Categories tabulky, neodebral soubor brožury ze systému souborů webového serveru. Aktualizujte Průzkumník řešení a uvidíte, že Test.pdf se ve ~/Brochures složce stále nachází.

Soubor Test.pdf nebyl odstraněn ze systému souborů webového serveru.

Obrázek 8: Soubor Test.pdf nebyl odstraněn ze systému souborů webového serveru

Krok 5: Odebrání odstraněného souboru brožury kategorie

Jednou z nevýhod ukládání binárních dat mimo databázi je, že při odstranění přidruženého záznamu databáze je potřeba provést další kroky k vyčištění těchto souborů. GridView a ObjectDataSource poskytují události, které se aktivují před i po provedení příkazu delete. Ve skutečnosti potřebujeme vytvořit obslužné rutiny událostí pro události před akcí i po akci. Před odstraněním záznamu Categories musíme určit cestu k jeho souboru PDF, ale nechceme ho odstranit před odstraněním kategorie pro případ, že dojde k výjimce a kategorie se neodstraní.

Událost GridView s se RowDeleting aktivuje před vyvolání příkazu ObjectDataSource s delete, zatímco jeho RowDeleted událost se aktivuje po. Pomocí následujícího kódu vytvořte obslužné rutiny událostí pro tyto dvě události:

' 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

V obslužné rutině RowDeletingCategoryID události je odstraněný řádek odebrán z kolekce GridView s DataKeys , ke které lze přistupovat v této obslužné rutině události prostřednictvím e.Keys kolekce. Dále se vyvolá třída sGetCategoryByCategoryID(categoryID), CategoriesBLL která vrátí informace o odstraněné záznamu. Pokud vrácený CategoriesDataRow objekt nemáNULL``BrochurePath hodnotu, uloží se do proměnné deletedCategorysPdfPath stránky, aby bylo možné soubor odstranit v obslužné rutině RowDeleted události.

Poznámka

Místo načítání BrochurePath podrobností o záznamu Categories odstraněného v RowDeleting obslužné rutině události jsme mohli alternativně přidat BrochurePath do vlastnosti GridView s DataKeyNames a přistupovat k hodnotě záznamu prostřednictvím e.Keys kolekce. Pokud byste to udělali, mírně by se zvětšila velikost zobrazení objektu GridView, ale snížila by se množství potřebného kódu a ušetřila by se cesta k databázi.

Po vyvolání základního příkazu delete ObjectDataSource se aktivuje obslužná rutina události GridView s RowDeleted . Pokud při odstraňování dat nebyly žádné výjimky a existuje hodnota pro deletedCategorysPdfPath, soubor PDF se ze systému souborů odstraní. Všimněte si, že tento dodatečný kód není potřeba k vyčištění binárních dat kategorie přidružených k obrázku. Je to proto, že data obrázku jsou uložená přímo v databázi, takže odstraněním Categories řádku odstraníte také data obrázku dané kategorie.

Po přidání dvou obslužných rutin událostí spusťte tento testovací případ znovu. Při odstraňování kategorie se odstraní také její přidružený SOUBOR PDF.

Aktualizace binárních dat přidružených k existujícímu záznamu přináší některé zajímavé výzvy. Zbývající část tohoto kurzu se ponoří do možností aktualizace brožury a obrázku. Krok 6 popisuje techniky aktualizace informací brožury a krok 7 se zabývá aktualizací obrázku.

Krok 6: Aktualizace brožury kategorie

Jak je popsáno v kurzu Přehled vložení, aktualizace a odstranění dat, GridView nabízí integrovanou podporu úprav na úrovni řádků, která může být implementována zaškrtnutím políčka, pokud je jeho podkladový zdroj dat správně nakonfigurovaný. ObjectDataSource v současné době ještě není nakonfigurovaný tak, CategoriesDataSource aby zahrnoval podporu aktualizací, takže ji přidáme.

V průvodci ObjectDataSource klikněte na odkaz Konfigurovat zdroj dat a pokračujte druhým krokem. Vzhledem k tomu, DataObjectMethodAttribute že se používá v CategoriesBLL, měl by být rozevírací seznam UPDATE automaticky naplněn přetížením UpdateCategory , které přijímá čtyři vstupní parametry (pro všechny sloupce kromě Picture). Změňte ho tak, aby se používalo přetížení s pěti parametry.

Nakonfigurujte ObjectDataSource tak, aby používal metodu UpdateCategory, která obsahuje parametr pro picture.

Obrázek 9: Konfigurace objektu ObjectDataSource tak, aby používal metodu UpdateCategory , která obsahuje parametr pro Picture (kliknutím zobrazíte obrázek v plné velikosti)

ObjectDataSource teď bude obsahovat hodnotu své UpdateMethod vlastnosti a odpovídající UpdateParameter s. Jak je uvedeno v kroku 4, Visual Studio při použití průvodce Konfigurovat zdroj dat nastaví vlastnost ObjectDataSource OldValuesParameterFormatString na original_{0} . To způsobí problémy s vyvoláním metody update a odstranění. Proto buď tuto vlastnost úplně vymažte, {0}nebo ji resetujte na výchozí hodnotu .

Po dokončení průvodce a opravě OldValuesParameterFormatStringby deklarativní kód ObjectDataSource měl vypadat takto:

<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>

Pokud chcete zapnout předdefinované funkce úprav GridView, zaškrtněte možnost Povolit úpravy z inteligentní značky GridView. Tím se vlastnost CommandField ShowEditButton nastaví na True, čímž se přidá tlačítko Upravit (a tlačítka Aktualizovat a Zrušit pro upravovaný řádek).

Konfigurace objektu GridView pro podporu úprav

Obrázek 10: Konfigurace objektu GridView pro podporu úprav (kliknutím zobrazíte obrázek v plné velikosti)

Přejděte na stránku v prohlížeči a klikněte na jedno z tlačítek Upravit na řádku. Vázaná CategoryName pole a Description se vykreslí jako textová pole. TemplateField BrochurePath nemá EditItemTemplate, takže bude dál zobrazovat ItemTemplate odkaz na brožuru. ImageField Picture se vykreslí jako TextBox, jehož Text vlastnost je přiřazena hodnota ImageField s DataImageUrlField , v tomto případě CategoryID.

GridView nemá rozhraní pro úpravy pro BrožuruPath

Obrázek 11: GridView nemá rozhraní pro úpravy (BrochurePathkliknutím zobrazíte obrázek v plné velikosti)

PřizpůsobeníBrochurePathrozhraní pro úpravy s

Pro TemplateField potřebujeme vytvořit rozhraní pro BrochurePath úpravy, které uživateli umožní:

  • Nechejte brožuru kategorie tak, jak je.
  • Aktualizujte brožuru kategorie tak, že nahrajete novou brožuru, nebo
  • Úplně odeberte brožuru kategorie (v případě, že kategorie už nemá přidruženou brožuru).

Potřebujeme také aktualizovat Picture rozhraní pro úpravy ImageField, ale dostaneme se k tomu v kroku 7.

Z inteligentní značky GridView klikněte na odkaz Upravit šablony a v rozevíracím seznamu vyberte BrochurePath TemplateField s EditItemTemplate . Přidejte do této šablony webový ovládací prvek RadioButtonList a nastavili jeho ID vlastnost na BrochureOptions a jeho AutoPostBack vlastnost na True. V okno Vlastnosti klikněte na tři tečky ve Items vlastnosti , čímž se zobrazí ListItem Editor Kolekce. Přidejte následující tři možnosti s Value 1, 2 a 3 v uvedeném pořadí:

  • Použít aktuální brožuru
  • Odebrat aktuální brožuru
  • Nahrát novou brožuru

Nastavte první ListItem vlastnost s Selected na Truehodnotu .

Přidání tří položek seznamu do seznamu RadioButtonList

Obrázek 12: Přidání tří ListItem s do seznamu přepínačů

Pod RadioButtonList přidejte ovládací prvek FileUpload s názvem BrochureUpload. Nastavte jeho Visible vlastnost na False.

Přidání ovládacích prvků RadioButtonList a FileUpload do EditItemTemplate

Obrázek 13: Přidání ovládacího prvku RadioButtonList a FileUpload do EditItemTemplate (kliknutím zobrazíte obrázek v plné velikosti)

Tento RadioButtonList poskytuje tři možnosti pro uživatele. Myšlenka je taková, že ovládací prvek SouborUpload se zobrazí pouze v případě, že je vybrána poslední možnost Nahrát novou brožuru. Chcete-li toho dosáhnout, vytvořte obslužnou rutinu události pro událost RadioButtonList SelectedIndexChanged a přidejte následující kód:

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

Vzhledem k tomu, že ovládací prvky RadioButtonList a FileUpload jsou v rámci šablony, musíme napsat trochu kódu pro programový přístup k těmto ovládacím prvkům. Obslužné SelectedIndexChanged rutině události je předán odkaz RadioButtonList ve vstupním parametru sender . Abychom získali ovládací prvek FileUpload, musíme získat nadřazený ovládací prvek RadioButtonList a použít metodu odsud FindControl("controlID") . Jakmile máme odkaz na oba RadioButtonList a FileUpload ovládací prvky FileUpload ovládacího prvku s Visible je nastavena na True pouze v případě, že RadioButtonList s SelectedValue rovná 3, což je Value pro Nahrát novou brožuru ListItem.

Když je tento kód na místě, chvíli si vyzkoušejte rozhraní pro úpravy. Klikněte na tlačítko Upravit u řádku. Na začátku by měla být vybraná možnost Použít aktuální brožuru. Změna vybraného indexu způsobí zpětné odeslání. Pokud je vybrána třetí možnost, zobrazí se ovládací prvek FileUpload, jinak je skrytý. Obrázek 14 znázorňuje rozhraní pro úpravy při prvním kliknutí na tlačítko Upravit; Obrázek 15 znázorňuje rozhraní po výběru možnosti Nahrát novou brožuru.

Možnost Použít aktuální brožuru je na začátku vybraná.

Obrázek 14: Zpočátku je vybraná možnost Použít aktuální brožuru (kliknutím zobrazíte obrázek v plné velikosti).

Volba možnosti Nahrát novou brožuru Zobrazí ovládací prvek SouborNahrání.

Obrázek 15: Volba možnosti Nahrát novou brožuru zobrazí ovládací prvek SouborNahrání (kliknutím zobrazíte obrázek v plné velikosti).

Uložení souboru brožury a aktualizaceBrochurePathsloupce

Po kliknutí na tlačítko Update objektu GridView se aktivuje jeho RowUpdating událost. ObjectDataSource s update příkaz je vyvolána a pak se aktivuje událost GridView s RowUpdated . Stejně jako u pracovního postupu odstraňování potřebujeme vytvořit obslužné rutiny událostí pro obě tyto události. V obslužné rutině RowUpdating události musíme určit, jaká akce se má provést, na SelectedValue základě hodnoty BrochureOptions RadioButtonList:

  • SelectedValue Pokud je 1, chceme i nadále používat stejné BrochurePath nastavení. Proto musíme nastavit parametr ObjectDataSource s brochurePath na existující BrochurePath hodnotu aktualizovaného záznamu. Parametr ObjectDataSource s brochurePath lze nastavit pomocí .e.NewValues["brochurePath"] = value
  • Pokud je hodnota SelectedValue 2, chceme nastavit hodnotu záznamu BrochurePath na NULL. Toho lze dosáhnout nastavením parametru ObjectDataSource na brochurePath hodnotu , což vede k Nothingpoužití databáze NULL v příkazu UPDATE . Pokud už existuje soubor brožury, který se odebírá, musíme ho odstranit. Chceme to ale udělat jenom v případě, že se aktualizace dokončí bez vyvolání výjimky.
  • SelectedValue Pokud je hodnota 3, chceme zajistit, aby uživatel nahrál soubor PDF, a pak ho uložit do systému souborů a aktualizovat hodnotu sloupce záznamuBrochurePath. Kromě toho, pokud existuje soubor brožury, který je nahrazován, musíme odstranit předchozí soubor. Chceme to ale udělat jenom v případě, že se aktualizace dokončí bez vyvolání výjimky.

Kroky, které je třeba provést, když RadioButtonList s SelectedValue je 3, jsou prakticky stejné jako kroky používané DetailsView s ItemInserting obslužnou rutinou události. Tato obslužná rutina události se spustí při přidání nového záznamu kategorie z ovládacího prvku DetailsView, který jsme přidali v předchozím kurzu. Proto se nám doporučuje refaktorovat tuto funkci do samostatných metod. Konkrétně jsme běžné funkce přesunuli do dvou metod:

  • ProcessBrochureUpload(FileUpload, out bool) přijímá jako vstup instanci ovládacího prvku FileUpload a výstupní logickou hodnotu, která určuje, jestli má operace odstranění nebo úpravy pokračovat, nebo jestli by měla být zrušena kvůli chybě ověření. Tato metoda vrátí cestu k uloženému souboru nebo null pokud nebyl uložen žádný soubor.
  • DeleteRememberedBrochurePath odstraní soubor určený cestou v proměnné deletedCategorysPdfPath stránky, pokud deletedCategorysPdfPath není null.

Kód pro tyto dvě metody následuje. Všimněte si podobnosti mezi ProcessBrochureUpload a obslužnou rutinou události DetailsView ItemInserting z předchozího kurzu. V tomto kurzu jsme aktualizovali obslužné rutiny událostí DetailsView tak, aby používaly tyto nové metody. Stáhněte si kód přidružený k tomuto kurzu, abyste viděli úpravy obslužných rutin událostí DetailsView.

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

Obslužné rutiny událostí GridView RowUpdating a RowUpdated používají ProcessBrochureUpload metody a DeleteRememberedBrochurePath , jak ukazuje následující kód:

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

Všimněte si, jak RowUpdating obslužná rutina události používá řadu podmíněných příkazů k provedení příslušné akce na BrochureOptions základě hodnoty vlastnosti RadioButtonList s SelectedValue .

S tímto kódem můžete upravit kategorii a nechat ji použít její aktuální brožuru, nepoužívat žádnou brožuru nebo nahrát novou. Pokračujte a vyzkoušejte to. Nastavte zarážky v RowUpdating obslužných rutinách událostí a RowUpdated , abyste získali představu o pracovním postupu.

Krok 7: Nahrání nového obrázku

Rozhraní Picture pro úpravy ImageField se vykreslí jako textové pole naplněné hodnotou z jeho DataImageUrlField vlastnosti. Během úprav pracovního postupu, GridView předá parametr ObjectDataSource s parametr s název hodnotu ImageField s DataImageUrlField vlastnost a parametr s hodnotu hodnotu zadanou do textového pole v rozhraní pro úpravy. Toto chování je vhodné, pokud je obrázek uložen jako soubor v systému souborů a DataImageUrlField obsahuje úplnou adresu URL obrázku. Za takových okolností rozhraní pro úpravy zobrazí adresu URL obrázku v textovém poli, kterou uživatel může změnit a uložit zpět do databáze. Toto výchozí rozhraní neumožňuje uživateli nahrát nový obrázek, ale umožňuje mu změnit adresu URL obrázku z aktuální hodnoty na jinou. Pro účely tohoto kurzu však výchozí rozhraní ImageField pro úpravy nestačí, protože Picture binární data jsou uložena přímo v databázi a DataImageUrlField vlastnost obsahuje pouze CategoryID.

Abychom lépe pochopili, co se stane v našem kurzu, když uživatel upraví řádek pomocí pole ImageField, podívejte se na následující příklad: uživatel upraví řádek s CategoryID hodnotou 10, což způsobí Picture , že ImageField se vykresluje jako textové pole s hodnotou 10. Představte si, že uživatel změní hodnotu v tomto textovém poli na 50 a klikne na tlačítko Aktualizovat. Dojde k postback a GridView zpočátku vytvoří parametr s názvem CategoryID s hodnotou 50. Než však Objekt GridView odešle tento parametr (a CategoryName parametry a Description ), přidá hodnoty z DataKeys kolekce. Proto přepíše CategoryID parametr základní CategoryID hodnotou aktuálního řádku 10. Stručně řečeno, rozhraní pro úpravy ImageField nemá žádný vliv na pracovní postup úprav pro tento kurz, protože názvy vlastnosti ImageField s DataImageUrlField a hodnoty mřížky DataKey jsou stejné.

I když pole ImageField usnadňuje zobrazení obrázku založeného na databázových datech, nechceme v rozhraní pro úpravy poskytovat textové pole. Místo toho chceme nabídnout ovládací prvek SouborUpload, který může koncový uživatel použít ke změně obrázku kategorie. BrochurePath Na rozdíl od hodnoty jsme se v těchto kurzech rozhodli vyžadovat, aby každá kategorie měla obrázek. Proto nemusíme nechat uživatele označit, že neexistuje přidružený obrázek. Uživatel může buď nahrát nový obrázek, nebo nechat aktuální obrázek tak, jak je.

Pokud chcete přizpůsobit rozhraní pro úpravy ImageField, musíme ho převést na TemplateField. V inteligentní značce GridView klikněte na odkaz Upravit sloupce, vyberte ImageField a klikněte na odkaz Převést toto pole na TemplateField.

Převod ImageField na TemplateField

Obrázek 16: Převod ImageField na TemplateField

Převod ImageField na TemplateField tímto způsobem vygeneruje TemplateField se dvěma šablonami. Jak ukazuje následující deklarativní syntaxe, obsahuje ovládací prvek Image Web, ItemTemplate jehož ImageUrl vlastnost je přiřazena pomocí syntaxe datové vazby založené na ImageField a DataImageUrlFieldDataImageUrlFormatString vlastnosti. Obsahuje EditItemTemplate TextBox, jehož Text vlastnost je vázána na hodnotu určenou DataImageUrlField vlastností .

<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>

Musíme aktualizovat EditItemTemplate , aby používal ovládací prvek FileUpload. Z inteligentní značky GridView s klikněte na odkaz Upravit šablony a pak v rozevíracím seznamu vyberte Picture TemplateField s EditItemTemplate . V šabloně by se mělo zobrazit textové pole, které toto odebere. Dále přetáhněte ovládací prvek SouborUpload z panelu nástrojů do šablony a nastavte ho ID na PictureUpload. Přidejte také text Pokud chcete změnit obrázek kategorie, zadejte nový obrázek. Chcete-li zachovat stejný obrázek kategorie, nechte pole v šabloně prázdné.

Přidání ovládacího prvku FileUpload do EditItemTemplate

Obrázek 17: Přidání ovládacího prvku FileUpload do EditItemTemplate (Kliknutím zobrazíte obrázek v plné velikosti)

Po přizpůsobení rozhraní pro úpravy zobrazte průběh v prohlížeči. Při prohlížení řádku v režimu jen pro čtení se obrázek kategorie zobrazí stejně jako předtím, ale kliknutím na tlačítko Upravit se vykreslí sloupec obrázku jako text s ovládacím prvku SouborNahrání.

Rozhraní pro úpravy obsahuje ovládací prvek FileUpload.

Obrázek 18: Rozhraní pro úpravy obsahuje ovládací prvek SouborUpload (kliknutím zobrazíte obrázek v plné velikosti)

Vzpomeňte si, že ObjectDataSource je nakonfigurována tak, aby volala metodu CategoriesBLL třídy s UpdateCategory , která přijímá jako vstup binární data obrázku Byte jako pole. Pokud je Nothingtoto pole , je však volána alternativní UpdateCategory přetížení, které vydává UPDATE příkaz SQL, který neupravuje Picture sloupec, a tím ponechá aktuální obrázek kategorie beze změny. Proto v obslužné rutině události GridView RowUpdating musíme programově odkazovat na PictureUpload ovládací prvek FileUpload a zjistit, jestli byl soubor nahrán. Pokud nebyl nahrán, pak nechceme zadat hodnotu parametru picture . Na druhou stranu, pokud byl soubor nahrán v ovládacím PictureUpload prvku SouborUpload, chceme zajistit, aby se jednalo o soubor JPG. Pokud ano, můžeme jeho binární obsah odeslat do ObjectDataSource prostřednictvím parametru picture .

Podobně jako u kódu použitého v kroku 6 už velká část kódu, který zde potřebujeme, v obslužné rutině události DetailsView ItemInserting existuje. Proto jsem refaktoroval běžné funkce na novou metodu a aktualizoval obslužnou rutinu ItemInserting události tak, ValidPictureUploadaby používala tuto metodu.

Na začátek obslužné rutiny události GridView s RowUpdating přidejte následující kód. Je důležité, aby tento kód byl před kódem, který ukládá soubor brožury, protože nechceme uložit brožuru do systému souborů webového serveru, pokud je odeslán neplatný soubor obrázku.

' 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

Metoda ValidPictureUpload(FileUpload) přebírá ovládací prvek FileUpload jako svůj jediný vstupní parametr a kontroluje příponu nahraného souboru, aby se zajistilo, že nahraný soubor je JPG. Volá se pouze v případě, že se nahraje soubor s obrázkem. Pokud se nenahraje žádný soubor, parametr picture se nenastaví, a proto použije výchozí hodnotu Nothing. Pokud se obrázek nahrál a ValidPictureUpload vrátí True, parametru picture se přiřadí binární data nahraného obrázku; pokud metoda vrátí Falsehodnotu , pracovní postup aktualizace se zruší a obslužná rutina události se ukončí.

Kód ValidPictureUpload(FileUpload) metody, který byl refaktorován z obslužné rutiny události DetailsView ItemInserting , následuje:

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

Krok 8: Nahrazení obrázků původních kategorií za JPG

Vzpomeňte si, že původních osm kategorií obrázků jsou rastrové soubory zabalené v záhlaví OLE. Teď, když jsme přidali možnost upravit existující obrázek záznamu, udělejte si chvilku a nahraďte tyto rastrové obrázky jpgy. Pokud chcete dál používat obrázky aktuální kategorie, můžete je převést na soubory JPG provedením následujících kroků:

  1. Uložte rastrové obrázky na pevný disk. Přejděte na UpdatingAndDeleting.aspx stránku v prohlížeči a pro každou z prvních osmi kategorií klikněte pravým tlačítkem myši na obrázek a zvolte, že chcete obrázek uložit.
  2. Otevřete obrázek v editoru obrázků podle svého výběru. Můžete použít například Microsoft Malování.
  3. Uložte rastrový obrázek jako obrázek JPG.
  4. Aktualizujte obrázek kategorie prostřednictvím rozhraní pro úpravy pomocí souboru JPG.

Po úpravě kategorie a nahrání obrázku JPG se obrázek v prohlížeči nevykreslí, protože DisplayCategoryPicture.aspx stránka odstraní prvních 78 bajtů z obrázků z prvních osmi kategorií. Opravte to odebráním kódu, který provádí vyjmutí hlaviček OLE. Jakmile to uděláte, obslužná DisplayCategoryPicture.aspx``Page_Load rutina události by měla mít pouze následující kód:

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

Poznámka

Rozhraní UpdatingAndDeleting.aspx pro vkládání a úpravy stránek by mohlo znamenat trochu víc práce. Description A CategoryName BoundFields v DetailsView a GridView by měly být převedeny na TemplateFields. Vzhledem k tomu CategoryName , že nepovoluje NULL hodnoty, měl by být přidán RequiredFieldValidator. Description A TextBox by pravděpodobně měl být převeden na víceřádkové TextBox. Tyto dokončovací úpravy nechávám jako cvičení pro vás.

Souhrn

Tento kurz doplňuje náš pohled na práci s binárními daty. V tomto kurzu a předchozích třech jsme viděli, jak je možné binární data ukládat v systému souborů nebo přímo v databázi. Uživatel poskytuje systému binární data tak, že vybere soubor z pevného disku a nahraje ho na webový server, kde může být uložen v systému souborů nebo vložen do databáze. ASP.NET 2.0 obsahuje ovládací prvek FileUpload, který poskytuje takové rozhraní tak snadné, jako je přetažení. Jak je však uvedeno v kurzu Nahrávání souborů , ovládací prvek FileUpload je vhodný pouze pro relativně malé nahrávání souborů, ideálně nepřekračuje megabajt. Prozkoumali jsme také, jak přidružit nahraná data k podkladovému datovému modelu a jak upravit a odstranit binární data z existujících záznamů.

Naše další sada kurzů zkoumá různé techniky ukládání do mezipaměti. Ukládání do mezipaměti poskytuje způsob, jak zlepšit celkový výkon aplikace tím, že vezme výsledky nákladných operací a uloží je do umístění, ke kterému se dá rychleji přistupovat.

Všechno nejlepší na programování!

O autorovi

Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.

Zvláštní poděkování

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavní revidující pro tento kurz byla Teresa Murphyová. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.