Pokud klasickým způsobem pomocí průvodce vytvoříme data binding kontajner podporující editaci (například FormView, DetailsView, DataList nebo GridView), je výsledkem přibližně následující kód:
<asp:FormView ID="FormView1" runat="server" DataSourceID="SqlDataSource1" DataKeyNames="CustomerID">
<EditItemTemplate>
<!-- tady jsou editační prvky -->
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update" Text="Update" />
<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel" />
</EditItemTemplate>
<InsertItemTemplate>
<!-- tady jsou editační prvky -->
<asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert" Text="Insert" />
<asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel" />
</InsertItemTemplate>
<ItemTemplate>
<!-- tady jsou editační prvky -->
<asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit" />
<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete" />
<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New" Text="New" />
</ItemTemplate>
</asp:FormView>
Pro účely tohoto článku nás zajímají tlačítka a jejich vlastnosti CommandName a CommandArguments.
Vlastnosti CommandName a CommandArgument
Vlastnost CommandName mají všechna tlačítka, lépe řečeno všechny ovládací prvky implementující interface System.Web.UI.WebControls.IButtonControl.
Po kliknutí na tlačítko, které je obsaženo v databound prvcích se nad daným prvkem vyvolá událost ItemCommand. Její handler dostane na vstupu argument e, typu CommandEventArgs. A ten má vlastnosti CommandName a CommandArgument, do kterých se zkopírují hodnoty vlastností toho tlačítka, na které uživatel kliknul.
Tento mechanismus je v ASP.NET proto, aby umožnil provádění databindingových operací v závislosti na různých akcích. Nezáleží na typu controlu, který událost vyvolá, ani na tom, jaký konkrétní prvek to byl.
U rozsáhlého formuláře můžete například chtít, aby tlačítka pro odeslání byla zdvojená - jednou na začátku formuláře, jednou na jeho konci. Případně některé funkce nechcete implementovat vůbec. Pokud byste ve shora uvedeném případě třeba nechtěli umožnit mazání záznamu, stačilo by zrušit prvek s CommandName="Delete". Nebo chcete tlačítko pro mazání zobrazit v editačním formuláři - stačí ho přesunout do EditItemTemplate.
Prvky pro databinding v sobě mají přímo vestavěnou podporu pro některé příkazy, odpovídající základním operacím jako je vložení záznamu, aktualizace a smazání (Insert, Update, Delete), případně příkazy pro přepnutí controlu do odpovídajícího režimu (New, Edit, Cancel).
Některé operace potřebují pro úspěšné vykonání ještě nějaký další parametr. Typickým příkladem je třeba operace stránkování, která je implementována pod příkazem Page. V takovém případě se do hry dostane druhá vlastnost, a to je CommandArgument. Ta může obsahovat parametr, který se k dané akci vztahuje. V případě příkazu Page jsou to klíčová slova First, Last, Prev, Next a nebo přímo číslo stránky, na kterou se má přejít.
Vytváření vlastních příkazů
Jak je v případě technologie .NET zvykem, je tato infrastruktura rozšiřitelná. Kromě vestavěných příkazů tedy můžete vytvářet příkazy vlastní a v události ItemCommand je zpracovávat.
Představme si situaci, kdy zobrazený záznam představuje nějaký požadavek, a akce které chceme podniknout jsou tento požadavek buďto přijmout nebo odmítnout. Tady nám standardní akce nejsou nic platné a odchytávat obyčejná klepnutí na tlačítka může být v řadě scénářů dosti komplikované.
Přidáme tedy do odpovídající šablony - patrně ItemTemplate - tlačítka pro přijetí a odmítnutí:
<asp:Button ID="AcceptButton" runat="server" CommandName="AcceptRq" CommandArgument='<%# Eval("RequestId") %>' Text="Přijmout" />
<asp:Button ID="RejectButton" runat="server" CommandName="RejectRq" CommandArgument='<%# Eval("RequestId") %>' Text="Odmítnout" />
V obsluze události ItemCommand bychom pak mohli zpracovat obdržený příkaz nějak takto:
protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e) {
using (var dc = new MyDataContext()) {
switch (e.CommandName) {
case "AcceptRq":
dc.AcceptRequest(e.CommandArgument);
break;
case "RejectRq":
dc.RejectRequest(e.CommandArgument);
break;
default:
break;
}
}
}
Pokud byste chtěli události ItemCommand využít k tomu, abyste se mohli controlu motat do vestavěných příkazů, je to samozřejmě možné, ale není to příliš dobrý nápad. K tomuto účelu můžete využít specializované události ItemUpdating a ItemUpdated (a jejich ekvivalenty pro další případy). Událost "-ing" se zavolá těsně před provedeném vlastní operace, událost "-ed" po dokončení.
Použití technologie příkazů vám dává možnost velmi elegantně řešit řadu běžných úkolů, kde si nevystačíte se základními příkazy typu SELECT, INSERT, UPDATE a DELETE.