Aktualizace a odstranění stávajících binárních dat (VB)
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é Insert
metody , Update
a 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ší.
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 CategoryName
hodnoty , Description
a 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.
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 CategoryName
hodnoty , Description
a 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 Nothing
př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.aspx
ná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.aspx
UpdatingAndDeleting.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
.
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í.
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é DeleteParameter
hodnotu . Vzpomeňte si, že při použití průvodce k určení metod sada Visual Studio nastaví vlastnost ObjectDataSource na OldValuesParameterFormatString
original_{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ě OldValuesParameterFormatString
by 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 True
hodnotu .
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 Categories
CategoryID
tabulkou 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.
Obrázek 6: Přidání testovací kategorie s brožurou a obrázkem (kliknutím zobrazíte obrázek v plné velikosti)
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í.
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ě RowDeleting
CategoryID
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.
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ě OldValuesParameterFormatString
by 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).
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
.
Obrázek 11: GridView nemá rozhraní pro úpravy (BrochurePath
kliknutím zobrazíte obrázek v plné velikosti)
PřizpůsobeníBrochurePath
rozhraní 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 True
hodnotu .
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
.
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.
Obrázek 14: Zpočátku je vybraná možnost Použít aktuální brožuru (kliknutím zobrazíte obrázek v plné velikosti).
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 aktualizaceBrochurePath
sloupce
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 sbrochurePath
na existujícíBrochurePath
hodnotu aktualizovaného záznamu. Parametr ObjectDataSource sbrochurePath
lze nastavit pomocí .e.NewValues["brochurePath"] = value
- Pokud je hodnota
SelectedValue
2, chceme nastavit hodnotu záznamuBrochurePath
naNULL
. Toho lze dosáhnout nastavením parametru ObjectDataSource nabrochurePath
hodnotu , což vede kNothing
použití databázeNULL
v příkazuUPDATE
. 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 nebonull
pokud nebyl uložen žádný soubor.DeleteRememberedBrochurePath
odstraní soubor určený cestou v proměnnédeletedCategorysPdfPath
stránky, pokuddeletedCategorysPdfPath
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.
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 DataImageUrlField
DataImageUrlFormatString
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é.
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í.
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 Nothing
toto 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, ValidPictureUpload
aby 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í False
hodnotu , 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ů:
- 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. - Otevřete obrázek v editoru obrázků podle svého výběru. Můžete použít například Microsoft Malování.
- Uložte rastrový obrázek jako obrázek JPG.
- 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.