V minulém díle jsme se naučili přidávat záznamy do databáze a použili jsme k tomuto účelu komponentu FormView. Již minule jsem naznačil, že tato komponenta umí záznamy i upravovat a mazat, takže se to dnes naučíme. Napíšeme si jednoduchou webovou aplikaci, která bude sloužit k evidenci hudebních CD. Abychom se moc nezdržovali, připravil jsem vám již databázi, kterou byste si měli stáhnout. Vytvořte si novou webovou aplikaci a rozbalte staženou databázi do složky App_Data.
Něco málo o konfiguraci ASP.NET aplikací
Abychom mohli s databází pracovat, musíme ji také zaregistrovat do konfiguračního souboru web.config. V minulých dílech jsme to udělali pomocí klikacího průvodce, ale není na škodu umět to i ručně. Otevřete tedy ve Visual Studiu soubor web.config a najděte řádek <connectionStrings />. Nahraďte jej tímto kódem:
<connectionStrings>
<add name="ConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\CdCatalog.mdf;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
Do sekce connectionStrings jsme tedy přidali nový connectionString s názvem ConnectionString. atribut connectionString obsahuje cestu k SQL serveru, cestu k souboru s databází a informace o tom, jak se máme k souboru přihlašovat. Vlastnost providerName říká, která třída se má použít pro práci s databází.
Připomínám, že v konfiguračním souboru aplikace se uchovávají všechna možná i nemožná nastavení. Výhodou je, že jeho struktura je poměrně snadno rozšiřitelná, a díky tomu si do něj můžeme přidat vlastní sekce, ve kterých budeme konfigurovat naše vlastní součásti aplikace, třeba nějaké vlastní komponenty atd. Nyní jsme do něj přidali informace o tom, kde je databáze a jak se k ní máme dostat. Doplňuji, že soubor web.config je zvenčí nedostupný, takže do něj můžete klidně ukládat hesla k databázím, žádný uživatel zvenku se k nim nemůže dostat (pokud je tedy server dobře zabezpečený).
Vytvoření MasterPage a stránky s přehledem alb
Z projektu smažte soubor Default.aspx a přidejte do něj novou položku MasterPage.master. Při přidávání odškrtněte políčko Place code in separate file, aby se nám zbytečně nevytvářely dva soubory. Pravým tlačítkem v podokně Solution Explorer na naši MasterPage klikněte a vyberte položku Add Content Page, aby se nám znovu vytvořila stránka Default.aspx a zaintegrovala se nám do naší MasterPage.
Přepněte se do nové stránky Default.aspx a přidejte do ní komponenty SqlDataSource a GridView. V režimu Design rozbalte podokno úloh komponenty SqlDataSource (je to taková ta malinká šipečka v horním pravém rohu) a vyberte možnost Configure Data Source. V dialogu vyberte náš ConnectionString, který jsme ručně přidali do konfigurace, pro sestavení dotazu zaškrtněte v tabulce Albums hvězdičku, aby se vybíraly všechny sloupce.
Potvrďte další kroky průvodce a po jeho skončení již budeme mít SqlDataSource nastaven.
V databázi máme tři tabulky - Albums obsahuje seznam alb, Genres obsahuje seznam žánrů hudby a Songs obsahuje skladby pro každé album. U každého alba uchováváme jeho název (Title), autora hudby (Author), interpreta (Interpret), rok vydání (Year), datum pořízení alba (DateBought), hodnocení (Rating) a žánr (GenreId), což je cizí klíč do tabulky žánrů. Rozbalte tedy podokno úloh komponenty GridView a vyberte SqlDataSource1 v rozbalovacím seznamu. Samy se nám vygenerovaly sloupce, nejjednodušší bude upravit je v okně kódu než v klikacím okénku.
Přepněte se teď do režimu Source a upravte hodnotu vlastnosti SelectCommand komponenty SqlDataSource1, nastavte jí jako hodnotu tento SQL příkaz:
SELECT [Albums].[AlbumId], [Albums].[Title] AS [Title], [Author], [Interpret], [Year], [DateBought], [Rating], [Genres].[Title] AS [Genre] FROM [Albums] LEFT JOIN [Genres] ON [Albums].[GenreId] = [Genres].[GenreId]
Protože chceme zobrazit název žánru pro každý zobrazený disk a tento název je uložen v jiné tabulce, spojil jsem v našem SQL dotazu příkazem LEFT JOIN tabulky Genres a Albums. Název žánru najdeme ve virtuálním sloupci Genre vytvořeném v dotazu. Pokud příkaz JOIN neznáte, přečtěte si článek Úvod do jazyka SQL. Aby se data v komponentě GridView zobrazila nějak rozumně, definici komponenty GridView změňte takto:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="AlbumId" DataSourceID="SqlDataSource1" Width="800px">
<Columns>
<asp:HyperlinkField DataTextField="Title" DataNavigateUrlFields="AlbumId" DataNavigateUrlFormatString="~/AlbumDetail.aspx?id={0}" HeaderText="Název alba" SortExpression="Title" />
<asp:BoundField DataField="Author" HeaderText="Autor hudby" SortExpression="Author" />
<asp:BoundField DataField="Interpret" HeaderText="Interpret" SortExpression="Interpret" />
<asp:BoundField DataField="Genre" HeaderText="Žánr" SortExpression="GenreId" />
<asp:BoundField DataField="Rating" HeaderText="Hodnocení" SortExpression="Rating" />
</Columns>
</asp:GridView>
Z názvu alba uděláme odkaz na stránku AlbumDetail.aspx, kde zobrazíme detaily daného alba. ID alba předáme v QueryStringu (parametr v URL) v parametru id. Adresa tedy bude např. AlbumDetail.aspx?id=1. Tuto stránku napíšeme nyní a budeme ji používat i k editaci a přidávání nových alb. Pokud aplikaci spustíte, bude stránka Default.aspx vypadat zhruba takto:
Zobrazení detailů alba
Vytvořte novou stránku vybráním volby Add Content Page v kontextové nabídce souboru MasterPage.master a přejmenujte ji na AlbumDetail.aspx. Přidejte do ní komponentu SqlDataSource a dále pak komponentu FormView, která dovede pracovat s jedním záznamem. Spusťte opět průvodce pro konfiguraci SQL příkazu a okna nastavte podle obrázků:
Dále klikněte na tlačítko WHERE, protože potřebujeme specifikovat v dotazu podmínku, aby se nám zobrazil jen jeden konkrétní požadovaný záznam, a to ten, který vytáhneme z parametru v URL.
Vyplňte zakroužkovaná pole a klikněte na tlačítko Add. Pak okno potvrďte tlačítkem OK. Do dotazu se doplní podmínka WHERE [AlbumId] = @AlbumId a parametr @AlbumId v SQL dotazu se automaticky vytáhne z parametru v URL.
Ještě než budete pokračovat dále, klikněte na tlačítko Advanced a podle obrázku zaškrtněte volbu Generate INSERT, UPDATE and DELETE statements. Tím se nám automaticky vygenerují i příkazy pro přidávání, úpravy a mazání záznamů v tabulce Albums.
Dokončete průvodce a naše komponenta SqlDataSource1 bude nastavena tak, jak potřebujeme. Když se podíváme na kód, který nám pro SqlDataSource1 průvodce vygeneroval, bude vypadat takto:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT * FROM [Albums] WHERE ([AlbumId] = @AlbumId)"
DeleteCommand="DELETE FROM [Albums] WHERE [AlbumId] = @AlbumId"
InsertCommand="INSERT INTO [Albums] ([GenreId], [Title], [Author], [Interpret], [Year], [DateBought], [Rating]) VALUES (@GenreId, @Title, @Author, @Interpret, @Year, @DateBought, @Rating)"
UpdateCommand="UPDATE [Albums] SET [GenreId] = @GenreId, [Title] = @Title, [Author] = @Author, [Interpret] = @Interpret, [Year] = @Year, [DateBought] = @DateBought, [Rating] = @Rating WHERE [AlbumId] = @AlbumId">
<SelectParameters>
<asp:QueryStringParameter Name="AlbumId" QueryStringField="id" Type="Int32" />
</SelectParameters>
<DeleteParameters>
<asp:Parameter Name="AlbumId" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="GenreId" Type="Int32" />
<asp:Parameter Name="Title" Type="String" />
<asp:Parameter Name="Author" Type="String" />
<asp:Parameter Name="Interpret" Type="String" />
<asp:Parameter Name="Year" Type="Int32" />
<asp:Parameter Name="DateBought" Type="DateTime" />
<asp:Parameter Name="Rating" Type="Byte" />
<asp:Parameter Name="AlbumId" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="GenreId" Type="Int32" />
<asp:Parameter Name="Title" Type="String" />
<asp:Parameter Name="Author" Type="String" />
<asp:Parameter Name="Interpret" Type="String" />
<asp:Parameter Name="Year" Type="Int32" />
<asp:Parameter Name="DateBought" Type="DateTime" />
<asp:Parameter Name="Rating" Type="Byte" />
</InsertParameters>
</asp:SqlDataSource>
Vidíme, že komponenta má nastaveny příslušné SQL příkazy ve vlastnostech SelectCommand, InsertCommand, DeleteCommand a UpdateCommand. Každý příkaz obsahuje několik příslušných parametrů, jejichž hodnoty se pošlou spolu s dotazem a dostanou se tak do příslušné tabulky. Každý parametr je včetně jeho tatového typu popsán v sekci SelectParameters, InsertParameters, DeleteParameters a UpdateParameters. Pokud je parametr deklarován značkou asp:QueryStringParameter, pak se jeho hodnota vezme z QueryStringu, tedy z parametru v URL dané stránky. Název parametru je specifikován vlastností QueryStringField. ASP.NET má i další druhy parametrů, které dokážou vytáhnout hodnotu z cookies, z nějakých komponent atd., můžete si napsat i vlastní typy parametrů. asp:Parameter je normální parametr, který nemá žádnou specifickou funkci, hodnoty těchto parametrů v sekcích InsertParameters, DeleteParameters a UpdateParameters nastaví automaticky komponenta FormView podle akce, kterou právě provádíme. Před vložením záznamu tedy FormView podle hodnot z formuláře vyplní parametry v sekci InsertParameters a pak zavolá na komponentě SqlDataSource příslušný INSERT příkaz. To samé platí i pro úpravy záznamů.
Zobrazení informací o albu
Protože opět budeme chtít vypsat název žánru místo jeho ID, opravte opět hodnotu vlastnosti SelectCommand v komponentě SqlDataSource1 na tuto hodnotu:
SELECT [Albums].[AlbumId], [Albums].[Title] AS [Title], [Albums].[GenreId], [Author], [Interpret], [Year], [DateBought], [Rating], [Genres].[Title] AS [Genre] FROM [Albums] LEFT JOIN [Genres] ON [Albums].[GenreId] = [Genres].[GenreId] WHERE ([AlbumId] = @AlbumId)
Nyní rozbalte podokno úloh komponenty FormView1 a vyberte v rozbalovacím seznamu komponentu SqlDataSource1. Komponenta FormView1 si automaticky zjistí strukturu tabulky podle předaného datového zdroje a podle toho vygeneruje své šablony pro zobrazení, editaci a přidávání záznamů. Tyto šablony si pochopitelně upravíme, aby vypadaly trochu k světu. Přepněte se do režimu Source a sekci ItemTemplate nahraďte tímto kódem:
<ItemTemplate>
<h1><asp:Label ID="TitleLabel" runat="server" Text='<%# Eval("Title") %>'></asp:Label></h1>
<table>
<tr>
<td>Autor hudby: </td>
<td><asp:Label ID="AuthorLabel" runat="server" Text='<%# Eval("Author") %>' Font-Bold="True"></asp:Label></td>
</tr>
<tr>
<td>Interpret: </td>
<td><asp:Label ID="InterpretLabel" runat="server" Text='<%# Eval("Interpret") %>' Font-Bold="True"></asp:Label></td>
</tr>
<tr>
<td>Žánr: </td>
<td><asp:Label ID="GenreLabel" runat="server" Text='<%# Eval("Genre") %>' Font-Bold="True"></asp:Label></td>
</tr>
<tr>
<td>Rok vydání: </td>
<td><asp:Label ID="YearLabel" runat="server" Text='<%# Eval("Year") %>' Font-Bold="True"></asp:Label></td>
</tr>
<tr>
<td>Datum pořízení: </td>
<td><asp:Label ID="DateBoughtLabel" runat="server" Text='<%# Eval("DateBought", "{0:d. MMMM yyyy}") %>' Font-Bold="True"></asp:Label></td>
</tr>
<tr>
<td>Hodnocení: </td>
<td><asp:Label ID="RatingLabel" runat="server" Text='<%# Eval("Rating") %>' Font-Bold="True"></asp:Label></td>
</tr>
</table>
<asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="[Upravit]"></asp:LinkButton>
<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="[Smazat]" OnClientClick="javascript: return confirm('Opravdu chcete toto album smazat?');"></asp:LinkButton>
<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New" Text="[Přidat]" PostBackUrl="~/AlbumDetail.aspx"></asp:LinkButton>
</ItemTemplate>
Na tomto kousku kódu by nám nemělo být téměř nic nového. Když vypisujeme datum pořízení, dali jsme jako druhý parametr příkazu Eval i formátovací řetězec d. MMMM yyyy, který zaručí, že se datum vypíše např. 12. listopadu 2007.
Na konci máme 3 tlačítka typu LinkButton. Důležitou jejich vlastností je CommandName - podle její hodnoty komponenta FormView pozná, co má udělat, takže kód neusíme psát my sami. První novinka je u tlačítka pro nové album, a je to vlastnost PostBackUrl. Tato vlastnost obsahuje adresu, na kterou se máme přepnout. Je to kvůli tomu, že když přidáváme nový záznam, nechceme, aby byl v URL parametr id s identifikátorem nějakého jiného záznamu. Nastavení této vlastnosti způsobí, že se formulář odešle na adresu AlbumDetail.aspx a to bez parametru id. To je přesně to, co chceme.
Druhá věc, kterou ještě neznáme, je vlastnost OnClientClick. Její hodnotou je klientský skript (javascript), který se spustí v prohlížeči při kliknutí na tlačítko. Pokud tento skript vrátí hodnotu false, akce se stornuje. confirm je javascriptová funkce, která zobrazí zprávu s předaným textem a s tlačítky OK a Storno. Pokud uživatel klikne na OK, vrátí se true a záznam se díky tomu smaže, pokud uživatel zvolí tlačítko Storno, skript vrátí hodnotu false a nic se nestane.
Poznámka: Komponenta LinkButton vyžaduje, aby prohlížeč podporoval javascript. Pokud prohlížeč javascript neumí, tato komponenta nebude fungovat. V podstatě je to totiž hypertextový odkaz, který odesílá formulář na server. Odesílat formulář na server hypertextovým odkazem ale v čistém HTML bez javascriptu možné není, jde to pouze pomocí tlačítka typu submit. Pokud potřebujete, aby stránka fungovala bez javascriptu, použijte klasickou komponentu Button, která funguje bez problémů. Je také na místě podotknout, že vlastnost OnClientClick bez javascriptu také nefunguje, formulář se v takovém případě odešle vždy. Na druhou stranu v dnešní době, kdy alespoň jednoduché javascripty umí i hloupý mobilní telefon, bych se nepodporou javascriptu moc netrápil. Většina komponent v ASP.NET bez zapnutého javascriptu funguje, LinkButton je jedna z výjimek.
Pokud si zobrazíme detail nějakého alba, bude to nyní vypadat nějak takto:
Šablony pro přidávání a úpravy alba
Protože to, co vygenerovalo Visual Studio jako šablonu pro přidávání a úpravy souborů, se nám samozřejmě nebude líbit ani hodit, zkusíme trochu uživatelům zpříjemnit přidávání záznamů. Upravte tedy šablonu takto:
<InsertItemTemplate>
<table>
<tr>
<td>Název alba: </td>
<td>
<asp:TextBox ID="TitleTextBox" runat="server" Text='<%# Bind("Title") %>' Width="300px"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="*" ControlToValidate="TitleTextBox"></asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td>Autor hudby: </td>
<td>
<asp:TextBox ID="AuthorTextBox" runat="server" Text='<%# Bind("Author") %>' Width="300px"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="*" ControlToValidate="AuthorTextBox"></asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td>Interpret: </td>
<td>
<asp:TextBox ID="InterpretTextBox" runat="server" Text='<%# Bind("Interpret") %>' Width="300px"></asp:TextBox>
</td>
</tr>
<tr>
<td>Žánr: </td>
<td>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [GenreId], [Title] FROM [Genres] ORDER BY [Title]"></asp:SqlDataSource>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlDataSource2" DataTextField="Title" DataValueField="GenreId" Width="300px" SelectedValue='<%#Bind("GenreId") %>'>
</asp:DropDownList>
</td>
</tr>
<tr>
<td>Rok vydání: </td>
<td>
<asp:TextBox ID="YearTextBox" runat="server" Text='<%# Bind("Year") %>' Width="100px"></asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server" ErrorMessage="*" ControlToValidate="YearTextBox" MinimumValue="1900" MaximumValue="3000"></asp:RangeValidator>
</td>
</tr>
<tr>
<td>Datum pořízení: </td>
<td>
<br />
<asp:Calendar ID="Calendar1" runat="server" SelectedDate='<%#Bind("DateBought") %>'></asp:Calendar>
<br />
</td>
</tr>
<tr>
<td>Hodnocení: </td>
<td>
<asp:RadioButtonList ID="RadioButtonList1" runat="server" CellPadding="3" RepeatDirection="Horizontal" RepeatLayout="Flow" SelectedValue='<%#Bind("Rating") %>'>
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem Selected="True">3</asp:ListItem>
<asp:ListItem>4</asp:ListItem>
<asp:ListItem>5</asp:ListItem>
</asp:RadioButtonList>
</td>
</tr>
</table>
<asp:Button ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" UseSubmitBehavior="False" Text="Zrušit"></asp:Button>
<asp:Button ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert" Text="Přidat album"></asp:Button>
</InsertItemTemplate>
Název alba a autor hudby jsou v databázi povinná pole, přidal jsem tedy za ně validátory RequiredFieldValidator a nastavil jim vlastnost ControlToValidate na ID komponent, které mají kontrolovat. Do pole pro zadání žánru jsem přidal komponenty SqlDataSource a komponentu DropDownList, což je rozbalovací seznam. Vlastnost DataTextField je název sloupce, jehož hodnoty se mají zobrazit v seznamu, a vlastnost DataValueField je název sloupce, jehož hodnoty se uloží do databáze. My zde použijeme hodnotu ze sloupce GenreId, což je ID žánru, do kterého album patří. Vlastnost SelectedValue pak provážeme s parametrem GenreId v komponentě SqlDataSource1 pomocí příkazu Bind, takže tento parametr dostane ID žánru, který uživatel vybere ze seznamu.
Do řádku, kde zadáváme rok vydání, jsem přidal komponentu RangeValidator, která kontroluje, jestli je zapsaná hodnota číslo a jestli není mimo nastavené hranice. Minimální rok je tedy 1900 a maximální 3000. Datum pořízení alba zadáme pomocí kalendáře, před něj a za něj jsem dal ještě značky <br />, aby se kalendář odsadil od toho, co je nad ním a pod ním. Vlastnost SelectedDate provážeme s příslušným parametrem, jehož hodnota se uloží do databáze.
Poslední sloupce s hodnocením jsem osadil komponentou RadioButtonList, do které jsem vložil položky s hodnotami od 1 do 5. Vlastnost RepeatDirection říká, jestli se položky budou řadit vedle sebe (hodnota Horizontal) nebo pod sebe (hodnota Vertical) a vlastnost RepeatLayout říká, jestli se má nebo nemá používat pro rozmístění přepínačů tabulka (v našem případě pro 1 řádek je to zbytečné).
Pak již následují dvě tlačítka, jedno pro přidání alba, druhé pro zrušení operace a návrat na hlavní stránku.
Je jasné, že vypisovat celý tento kód by nemuselo být příliš vhodné, já jsem akorát změnil to, co nám Visual Studio vygenerovalo. Pokud se přepnete do režimu Source a rozbalíte podokno úkolů komponenty FormView1, uvidíte odkaz Edit templates. Pokud na něj kliknete, můžete vizuálně upravovat obsah šablony. Hodí se to, pokud potřebujete nakonfigurovat vnořený SqlDataSource. Je ale dobré oba režimy kombinovat, úplně vše naklikat nejde, resp. jde, ale s nevalným výsledkem. Pro nakonfigurávání komponenty SqlDataSource je ale Design režim ideální.
Pokud se nyní v naší aplikaci rozhodneme přidat nový záznam, upravený formulář bude vypadat již o dost lépe, bude použitelnější a také bude kontrolovat, aby data nebyla zadána chybně.
Šablona pro úpravu záznamu
Šablona pro upravování záznamů bude vypadat velice podobně, jediný rozdíl je vlastně jen v tlačítkách na konci. Změňte tedy její kód takto:
<EditItemTemplate>
<table>
<tr>
<td>Název alba: </td>
<td>
<asp:TextBox ID="TitleTextBox" runat="server" Text='<%# Bind("Title") %>' Width="300px"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="*" ControlToValidate="TitleTextBox"></asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td>Autor hudby: </td>
<td>
<asp:TextBox ID="AuthorTextBox" runat="server" Text='<%# Bind("Author") %>' Width="300px"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="*" ControlToValidate="AuthorTextBox"></asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td>Interpret: </td>
<td>
<asp:TextBox ID="InterpretTextBox" runat="server" Text='<%# Bind("Interpret") %>' Width="300px"></asp:TextBox>
</td>
</tr>
<tr>
<td>Žánr: </td>
<td>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [GenreId], [Title] FROM [Genres] ORDER BY [Title]"></asp:SqlDataSource>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlDataSource2" DataTextField="Title" DataValueField="GenreId" Width="300px" SelectedValue='<%#Bind("GenreId") %>'>
</asp:DropDownList>
</td>
</tr>
<tr>
<td>Rok vydání: </td>
<td>
<asp:TextBox ID="YearTextBox" runat="server" Text='<%# Bind("Year") %>' Width="100px"></asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server" ErrorMessage="*" ControlToValidate="YearTextBox" MinimumValue="1900" MaximumValue="3000"></asp:RangeValidator>
</td>
</tr>
<tr>
<td>Datum pořízení: </td>
<td>
<br />
<asp:Calendar ID="Calendar1" runat="server" SelectedDate='<%#Bind("DateBought") %>'></asp:Calendar>
<br />
</td>
</tr>
<tr>
<td>Hodnocení: </td>
<td>
<asp:RadioButtonList ID="RadioButtonList1" runat="server" CellPadding="3" RepeatDirection="Horizontal" RepeatLayout="Flow" SelectedValue='<%#Bind("Rating") %>'>
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
<asp:ListItem>4</asp:ListItem>
<asp:ListItem>5</asp:ListItem>
</asp:RadioButtonList>
</td>
</tr>
</table>
<asp:Button ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" UseSubmitBehavior="False" Text="Zrušit"></asp:Button>
<asp:Button ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update" Text="Uložit změny"></asp:Button>
</EditItemTemplate>
Dokončení aneb až sem to šlo bez programování
Aplikace nyní funguje, umí přidávat, upravovat i mazat záznamy, a to jsme vlastně nenapsali jediný řádek kódu. Jediná věc, kterou komponenta FormView neumí, je postarat se o to, co se má stát po přidání záznamu, případně po jeho úpravě či smazání. Přepněte se proto do režimu Design a označte komponentu FormView1. V okně vlastností se přepněte do režimu Events kliknutím na ikonu .
Dvakrát klikněte do řádku ItemInserted, aby se nám vytvořila procedura této události. Událost ItemInserted se vyvolá hned poté, co je záznam do databáze přidán. Dovnitř této procedury napište tento kód v jazyce, který jste si zvolili:
Response.Redirect(ResolveClientUrl("~/Default.aspx"))
Response.Redirect(ResolveClientUrl("~/Default.aspx"));
Ten samý řádek vložte i do události ItemDeleted, která nastane hned poté, co je záznam z databáze odebrán. Response.Redirect je metoda, která provede přesměrování požadavku na zadanou adresu. Funkce ResolveClientUrl převede adresu s vlnovkovou notací na adresu relativní k adrese, na které je aktuálně klient. V této aplikaci jsme mohli napsat rovnou Response.Redirect("Default.aspx"), protože nemáme žádné stránky jinde než v kořenovém adresáři aplikace, ale je dobré si zvyknout používat tyto zápisy adres z jednoho prostého důvodu - ať jsme již na stránce v kterémkoliv adresáři na webu, použitím vlnovkové notace se dostaneme vždy tam, kam potřebujeme. Vlnovka ~ značí kořenový adresář aplikace.
Nakonec musíme ještě ošetřit kliknutí na tlačítka Zpět, chceme se opět přesměrovat na úvodní stránku se seznamem alb. Protože komponenta FormView nemá žádnou událost, která nastane při zrušení akce, nezbývá nám než odchytit přímo událost ItemCommand, která nastane vždy, když odešleme formulář komponentou, která má nastavenou vlastnost CommandName. Vytvořte tedy proceduru události ItemCommand a vložte do ní tento kód:
If String.Equals(e.CommandName, "Cancel", StringComparison.InvariantCultureIgnoreCase) Then
Response.Redirect(ResolveClientUrl("~/Default.aspx"))
End If
if (String.Equals(e.CommandName, "Cancel", StringComparison.InvariantCultureIgnoreCase))
Response.Redirect(ResolveClientUrl("~/Default.aspx"));
Tady jste si možná všimnuli zvláštního způsobu porovnávání dvou řetězců přes String.Equals. Tato metoda porovnává dva řetězce, její výhodou je ale to, že můžete zadat i třetí parametr, v našem případě InvariantCultureIgnoreCase, který určuje další parametry porovnávání. V tomto případě nerozlišuje mezi velkými a malými písmeny, což právě potřebujeme, názvy příkazů v komponentách totiž nejsou case-sensitive (Cancel je stejné jako cancel). Mohli bychom napsat také e.CommandName.ToLower() = "cancel", což by fungovalo stejně, ale to umí každý a navíc je to pomalejší, i když u takto krátkých slov je rozdíl neměřitelný. Nicméně String.Equals je systémové řešení a je dobré o něm vědět.
Závěrem
V příštím díle naši aplikaci dokončíme, naučíme se totiž pracovat se vzhledem a se skiny. Ukážeme si také, jak ASP.NET elegantně řeší některé nedomyšlenosti formulářových prvků v HTML a jejich stylování v CSS, které nám mohou nadělat problémy. Naši aplikaci pro evidenci hudebních CD převedeme do trochu "koukatelné" podoby. A samozřejmě přidáme do formulářů zobrazení seznamu skladeb v každém albu a umožníme jej uživatelům upravovat.