Udostępnij za pośrednictwem


Dodawanie kolumny przycisków radiowych do kontrolki GridView (VB)

Autor: Scott Mitchell

Pobierz plik PDF

W tym samouczku przedstawiono sposób dodawania kolumny przycisków radiowych do kontrolki GridView w celu zapewnienia użytkownikowi bardziej intuicyjnego sposobu wybierania pojedynczego wiersza kontrolki GridView.

Wprowadzenie

Kontrolka GridView oferuje wiele wbudowanych funkcji. Zawiera on wiele różnych pól do wyświetlania tekstu, obrazów, hiperlinków i przycisków. Obsługuje szablony do dalszego dostosowywania. Za pomocą kilku kliknięć myszy można ustawić kontrolkę GridView, w której można wybrać każdy wiersz za pomocą przycisku, lub włączyć edytowanie lub usuwanie możliwości. Pomimo wielu dostępnych funkcji, często będą istnieć sytuacje, w których należy dodać dodatkowe, nieobsługiwane funkcje. W tym samouczku i w kolejnych dwóch omówimy sposób ulepszania funkcji GridView w celu uwzględnienia dodatkowych funkcji.

Ten samouczek i następny z nich koncentrują się na ulepszaniu procesu wyboru wierszy. Zgodnie z analizą w elemecie Master/DetailView z kontrolką DetailsView z możliwością wyboru elementu Master GridView możemy dodać pole polecenia do kontrolki GridView, która zawiera przycisk Wybierz. Po kliknięciu zostanie zwrócona informacja zwrotna, a właściwość GridView zostanie SelectedIndex zaktualizowana do indeksu wiersza, którego przycisk Wybierz został kliknięty. W samouczku Master/Detail Using a Selectable Master GridView with a Details DetailView (Szczegóły) pokazano, jak używać tej funkcji do wyświetlania szczegółów dla wybranego wiersza GridView.

Gdy przycisk Wybierz działa w wielu sytuacjach, może nie działać również dla innych osób. Zamiast używać przycisku, do zaznaczenia są często używane dwa inne elementy interfejsu użytkownika: przycisk radiowy i pole wyboru. Możemy rozszerzyć kontrolkę GridView, aby zamiast przycisku Wybierz każdy wiersz zawierał przycisk radiowy lub pole wyboru. W scenariuszach, w których użytkownik może wybrać tylko jeden z rekordów GridView, przycisk radiowy może być preferowany przez przycisk Wybierz. W sytuacjach, w których użytkownik może potencjalnie wybrać wiele rekordów, takich jak w aplikacji poczty e-mail opartej na sieci Web, gdzie użytkownik może wybrać wiele wiadomości, aby usunąć pole wyboru oferuje funkcje, które nie są dostępne w interfejsach użytkownika przycisku Wybierz lub przycisk radiowy.

W tym samouczku przedstawiono sposób dodawania kolumny przycisków radiowych do kontrolki GridView. Poniższy samouczek eksploruje pola wyboru przy użyciu pól wyboru.

Krok 1. Tworzenie ulepszania stron sieci Web GridView

Zanim zaczniemy ulepszać element GridView w celu uwzględnienia kolumny przycisków radiowych, najpierw poświęćmy chwilę, aby utworzyć strony ASP.NET w naszym projekcie witryny internetowej, które będą potrzebne w tym samouczku i w następnych dwóch. Zacznij od dodania nowego folderu o nazwie EnhancedGridView. Następnie dodaj do tego folderu następujące strony ASP.NET, aby skojarzyć każdą stronę ze stroną wzorcową Site.master :

  • Default.aspx
  • RadioButtonField.aspx
  • CheckBoxField.aspx
  • InsertThroughFooter.aspx

Dodawanie stron ASP.NET dla samouczków dotyczących SqlDataSource-Related

Rysunek 1. Dodawanie stron ASP.NET dla samouczków SqlDataSource-Related

Podobnie jak w przypadku innych folderów Default.aspx , w EnhancedGridView folderze zostaną wyświetlone samouczki w swojej sekcji. Pamiętaj, że kontrolka SectionLevelTutorialListing.ascx użytkownika zapewnia tę funkcję. W związku z tym dodaj tę kontrolkę Default.aspx użytkownika, przeciągając ją z Eksplorator rozwiązań do widoku projektu strony.

Dodaj kontrolkę Użytkownika SectionLevelTutorialListing.ascx, aby Default.aspx

Rysunek 2. Dodawanie kontrolki SectionLevelTutorialListing.ascx użytkownika do Default.aspx (kliknij, aby wyświetlić obraz pełnowymiarowy)

Na koniec dodaj te cztery strony jako wpisy do Web.sitemap pliku. W szczególności dodaj następujące znaczniki po kontrolce SqlDataSource <siteMapNode>:

<siteMapNode 
    title="Enhancing the GridView" 
    url="~/EnhancedGridView/Default.aspx" 
    description="Augment the user experience of the GridView control.">
    <siteMapNode 
        url="~/EnhancedGridView/RadioButtonField.aspx" 
        title="Selection via a Radio Button Column" 
        description="Explore how to add a column of radio buttons in the GridView." />
    <siteMapNode 
        url="~/EnhancedGridView/CheckBoxField.aspx" 
        title="Selection via a Checkbox Column" 
        description="Select multiple records in the GridView by using a column of 
            checkboxes." />
    <siteMapNode 
        url="~/EnhancedGridView/InsertThroughFooter.aspx" 
        title="Add New Records through the Footer" 
        description="Learn how to allow users to add new records through the 
            GridView's footer." />
</siteMapNode>

Po zaktualizowaniu Web.sitemapprogramu poświęć chwilę, aby wyświetlić witrynę internetową samouczków za pośrednictwem przeglądarki. Menu po lewej stronie zawiera teraz elementy do edycji, wstawiania i usuwania samouczków.

Mapa witryny zawiera teraz wpisy dotyczące ulepszania samouczków GridView

Rysunek 3. Mapa witryny zawiera teraz wpisy dotyczące ulepszania samouczków GridView

Krok 2. Wyświetlanie dostawców w siatceView

Na potrzeby tego samouczka skompilujmy widok GridView zawierający listę dostawców z USA, a każdy wiersz GridView udostępnia przycisk radiowy. Po wybraniu dostawcy za pośrednictwem przycisku radiowego użytkownik może wyświetlić produkty dostawcy, klikając przycisk. Chociaż to zadanie może brzmieć trywialne, istnieje wiele subtelności, które sprawiają, że jest to szczególnie trudne. Zanim zagłębimy się w te subtelności, najpierw pobierzmy usługę GridView z listą dostawców.

Zacznij od otwarcia RadioButtonField.aspx strony w EnhancedGridView folderze, przeciągając element GridView z przybornika do Projektant. Ustaw wartość GridView na IDSuppliers i, na podstawie tagu inteligentnego, wybierz opcję utworzenia nowego źródła danych. W szczególności utwórz obiekt ObjectDataSource o nazwie SuppliersDataSource , który pobiera dane z SuppliersBLL obiektu.

Tworzenie nowego obiektuDataSource o nazwie SuppliersDataSource

Rysunek 4. Tworzenie nowego obiektuDataSource nazwane SuppliersDataSource (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Zrzut ekranu przedstawiający okno Konfigurowanie źródła danych — SuppliersDataSource z otwartym menu rozwijanym obiektu biznesowego. Wybrano pozycję DostawcyBLL, a przycisk Dalej został wyróżniony.

Rysunek 5. Konfigurowanie obiektu ObjectDataSource do używania SuppliersBLL klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Ponieważ chcemy wyświetlić listę tylko tych dostawców w USA, wybierz GetSuppliersByCountry(country) metodę z listy rozwijanej na karcie SELECT.

Zrzut ekranu przedstawiający okno Konfigurowanie źródła danych — SuppliersDataSource na karcie SELECT z otwartym menu rozwijanym metody. Opcja metody GetSupplierByCountry jest zaznaczona, a przycisk Dalej jest wyróżniony.

Rysunek 6. Konfigurowanie obiektu ObjectDataSource do używania SuppliersBLL klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Na karcie UPDATE (Brak) wybierz opcję (Brak), a następnie kliknij przycisk Dalej.

Zrzut ekranu przedstawiający okno Konfigurowanie źródła danych — SuppliersDataSource na karcie UPDATE z otwartym menu rozwijanym metody. Opcja metody (Brak) jest zaznaczona, a przycisk Dalej jest wyróżniony.

Rysunek 7. Konfigurowanie obiektu ObjectDataSource do używania SuppliersBLL klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

GetSuppliersByCountry(country) Ponieważ metoda akceptuje parametr, kreator Konfiguruj źródło danych wyświetla monit o źródło tego parametru. Aby określić twardą wartość (USA, w tym przykładzie), pozostaw listę rozwijaną Źródło parametrów ustawioną na Wartość Brak i wprowadź wartość domyślną w polu tekstowym. Kliknij przycisk Zakończ, aby zakończyć kreatora.

Użyj usa jako wartości domyślnej dla parametru kraju

Rysunek 8. Użyj usa jako wartości domyślnej parametru country (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy kreatora funkcja GridView będzie zawierać pole BoundField dla każdego pola danych dostawcy. Usuń wszystkie wartości , CompanyNameCityi Country BoundFields i zmień nazwę CompanyName właściwości BoundFields HeaderText na Dostawca. Po wykonaniu tej czynności składni deklaratywnej GridView i ObjectDataSource powinny wyglądać podobnie do poniższej.

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="CompanyName" HeaderText="Supplier" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="City" HeaderText="City" 
            SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" 
            SortExpression="Country" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
    <SelectParameters>
        <asp:Parameter DefaultValue="USA" Name="country" Type="String" />
    </SelectParameters>
</asp:ObjectDataSource>

Na potrzeby tego samouczka pozwólmy użytkownikowi wyświetlić wybrane produkty dostawcy na tej samej stronie co lista dostawców lub na innej stronie. Aby to uwzględnić, dodaj do strony dwa kontrolki sieci Web przycisku. Ustawiłem ID s z tych dwóch przycisków na ListProducts i SendToProducts, z pomysłem, że po ListProducts kliknięciu po powrocie nastąpi, a wybrane produkty dostawcy zostaną wyświetlone na tej samej stronie, ale po SendToProducts kliknięciu użytkownik zostanie whisked na innej stronie, która wyświetla listę produktów.

Rysunek 9 przedstawia kontrolkę Suppliers GridView i dwie kontrolki sieci Web przycisków po wyświetleniu za pośrednictwem przeglądarki.

Dostawcy z USA mają swoje nazwy, miasto i informacje o kraju wymienione

Rysunek 9. Dostawcy z USA Mają swoje nazwy, miasto i informacje o kraju wymienione (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 3. Dodawanie kolumny przycisków radiowych

W tym momencie obiekt Suppliers GridView ma trzy pola Granic wyświetlające nazwę firmy, miasto i kraj każdego dostawcy w USA. Nadal brakuje jednak kolumny przycisków radiowych. Niestety, GridView nie zawiera wbudowanego elementu RadioButtonField, w przeciwnym razie możemy po prostu dodać to do siatki i zrobić. Zamiast tego możemy dodać element TemplateField i skonfigurować go ItemTemplate tak, aby renderować przycisk radiowy, co powoduje kliknięcie przycisku radiowego dla każdego wiersza kontrolki GridView.

Początkowo możemy założyć, że żądany interfejs użytkownika można zaimplementować przez dodanie kontrolki Sieci Web RadioButton do ItemTemplate pola szablonu. Chociaż spowoduje to rzeczywiście dodanie jednego przycisku radiowego do każdego wiersza elementu GridView, przyciski radiowe nie mogą być zgrupowane i dlatego nie wykluczają się wzajemnie. Oznacza to, że użytkownik końcowy może jednocześnie wybrać wiele przycisków radiowych z kontrolki GridView.

Mimo że użycie kontrolki Sieci Web TemplateField of RadioButton nie oferuje potrzebnych funkcji, zaimplementujmy to podejście, ponieważ warto sprawdzić, dlaczego wynikowe przyciski radiowe nie są pogrupowane. Zacznij od dodania pola TemplateField do elementu GridView dostawców, co czyni go najbardziej lewym polem. Następnie z tagu inteligentnego GridView kliknij link Edytuj szablony i przeciągnij kontrolkę Sieci Web RadioButton z przybornika do pola szablonów ItemTemplate (zobacz Rysunek 10). Ustaw właściwość RadioButton ID na RowSelector i GroupName właściwość na SuppliersGroup.

Dodawanie kontrolki sieci Web RadioButton do elementu ItemTemplate

Rysunek 10. Dodawanie kontrolki sieci Web RadioButton do elementu ItemTemplate (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po dodaniu tych dodatków za pośrednictwem Projektant znaczniki GridView powinny wyglądać podobnie do następujących:

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:RadioButton ID="RowSelector" runat="server" 
                    GroupName="SuppliersGroup" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CompanyName" HeaderText="Supplier" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="City" HeaderText="City" 
            SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" 
            SortExpression="Country" />
    </Columns>
</asp:GridView>

Właściwość RadioButton GroupName jest używana do grupowania serii przycisków radiowych. Wszystkie kontrolki RadioButton o tej samej GroupName wartości są traktowane jako pogrupowane. Jednocześnie można wybrać tylko jeden przycisk radiowy z grupy. Właściwość GroupName określa wartość atrybutu renderowanego przycisku name radiowego. Przeglądarka sprawdza atrybuty przycisków radiowych, aby określić grupy przycisków name radiowych.

Za pomocą kontrolki RadioButton Web dodanej do ItemTemplateelementu , odwiedź tę stronę za pośrednictwem przeglądarki i kliknij przyciski radiowe w wierszach siatki. Zwróć uwagę, że przyciski radiowe nie są pogrupowane, dzięki czemu można wybrać wszystkie wiersze, jak pokazano na rysunku 11.

Przyciski radiowe GridView nie są grupowane

Rysunek 11. Przyciski radiowe GridView nie są grupowane (kliknij, aby wyświetlić obraz pełnowymiarowy)

Powodem, dla którego przyciski radiowe nie są pogrupowane, jest to, że ich renderowane name atrybuty są różne, mimo że mają to samo GroupName ustawienie właściwości. Aby zobaczyć te różnice, wykonaj widok/źródło w przeglądarce i sprawdź znacznik przycisku radiowego:

<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup" 
    type="radio" value="RowSelector" />

Zwróć uwagę, że zarówno name atrybuty, jak i id nie są dokładnymi wartościami określonymi w okno Właściwości, ale są poprzedzane wieloma innymi ID wartościami. Dodatkowe ID wartości dodane do przodu renderowanego id i name atrybuty to ID s przycisków radiowych nadrzędnych kontrole GridViewRow sID, GridView s , kontrolki Content s IDIDi formularzy IDsieci Web . Są one ID dodawane tak, aby każda renderowana kontrolka sieci Web w elemecie GridView ma unikatowe id wartości i name .

Każda renderowana kontrolka wymaga innej name kontrolki i id dlatego, że przeglądarka jednoznacznie identyfikuje każdą kontrolkę po stronie klienta i jak identyfikuje się z serwerem internetowym, jaka akcja lub zmiana wystąpiła po powrocie zwrotnej. Załóżmy na przykład, że chcemy uruchomić kod po stronie serwera za każdym razem, gdy stan sprawdzony elementu RadioButton został zmieniony. Możemy to osiągnąć, ustawiając właściwość RadioButton AutoPostBack na True i tworząc procedurę obsługi zdarzeń CheckChanged dla zdarzenia. Jeśli jednak renderowane name wartości i id dla wszystkich przycisków radiowych były takie same, po powrocie nie mogliśmy określić, jaki konkretny przycisk RadioButton został kliknięty.

Krótko mówiąc, nie możemy utworzyć kolumny przycisków radiowych w kontrolce GridView przy użyciu kontrolki RadioButton Web. Zamiast tego musimy użyć raczej archaicznych technik, aby upewnić się, że odpowiednie znaczniki są wstrzykiwane do każdego wiersza GridView.

Uwaga

Podobnie jak kontrolka RadioButton Web, kontrolka HTML przycisku radiowego, po dodaniu do szablonu, będzie zawierać unikatowy name atrybut, dzięki czemu przyciski radiowe w siatce niezgrupowane. Jeśli nie znasz kontrolek HTML, możesz zignorować tę notatkę, ponieważ rzadko używane są kontrolki HTML, szczególnie w ASP.NET 2.0. Jeśli jednak chcesz dowiedzieć się więcej, zobacz wpis w blogu K. Scott Allen Web Controls i kontrolki HTML.

Używanie kontrolki literału do wstrzykiwania znacznika przycisku radiowego

Aby poprawnie zgrupować wszystkie przyciski radiowe w elemecie GridView, musimy ręcznie wstrzyknąć znaczniki radiowe do elementu ItemTemplate. Każdy przycisk radiowy wymaga tego samego name atrybutu, ale powinien mieć unikatowy id atrybut (jeśli chcemy uzyskać dostęp do przycisku radiowego za pośrednictwem skryptu po stronie klienta). Gdy użytkownik wybierze przycisk radiowy i opublikuje stronę z powrotem, przeglądarka wyśle z powrotem wartość wybranego atrybutu przycisku value radiowego. W związku z tym każdy przycisk radiowy będzie potrzebował unikatowego value atrybutu. Na koniec po powrocie musimy pamiętać o dodaniu atrybutu checked do wybranego przycisku radiowego, w przeciwnym razie po wybraniu przez użytkownika zaznaczenia i wpisów przyciski radiowe powrócą do stanu domyślnego (wszystkie niezaznaczone).

Istnieją dwa podejścia, które można podjąć w celu wstrzyknięcia znaczników niskiego poziomu do szablonu. Jednym z nich jest wykonywanie kombinacji znaczników i wywołań do metod formatowania zdefiniowanych w klasie code-behind. Ta technika została po raz pierwszy omówiona w samouczku Using TemplateFields (Używanie pól szablonu w kontrolce GridView ). W naszym przypadku może to wyglądać mniej więcej tak:

<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>' 
    name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />

GetUniqueRadioButton W tym miejscu metody będą GetRadioButtonValue zdefiniowane w klasie kodu, która zwróciła odpowiednie id i value atrybuty wartości dla każdego przycisku radiowego. Takie podejście dobrze sprawdza się w przypadku przypisywania id atrybutów i value , ale w przypadku konieczności określenia checked wartości atrybutu, ponieważ składnia powiązania danych jest wykonywana tylko wtedy, gdy dane są najpierw powiązane z elementem GridView. W związku z tym jeśli element GridView ma włączony stan widoku, metody formatowania będą uruchamiane tylko wtedy, gdy strona zostanie załadowana po raz pierwszy (lub gdy element GridView jest jawnie odbicia do źródła danych), a zatem funkcja, która ustawia checked atrybut, nie będzie wywoływana po powrocie zwrotnej. Jest to raczej subtelny problem i nieco poza zakresem tego artykułu, więc pozostawię to w tym miejscu. Zachęcam jednak do wypróbowania powyższego podejścia i pracy nad tym punktem, w którym utkniesz. Mimo że takie ćwiczenie nie przybliży Cię do wersji roboczej, pomoże ona lepiej zrozumieć element GridView i cykl życia łączenia danych.

Inne podejście do wstrzykiwania niestandardowych, niskiego poziomu znaczników w szablonie i podejście, którego będziemy używać w tym samouczku, polega na dodaniu kontrolki Literał do szablonu. Następnie w programie obsługi zdarzeń GridView RowCreated lub RowDataBound kontrolce literału można uzyskać dostęp programowy, a jej Text właściwość ustawiona na znaczniki do emisji.

Zacznij od usunięcia elementu RadioButton z elementu TemplateField s ItemTemplate, zastępując go kontrolką Literał. Ustaw kontrolkę Literał s ID na RadioButtonMarkup.

Dodawanie kontrolki literału do elementu ItemTemplate

Rysunek 12. Dodawanie kontrolki literału do kontrolki ItemTemplate (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Następnie utwórz procedurę obsługi zdarzeń dla zdarzenia GridView.RowCreated Zdarzenie RowCreated jest uruchamiane raz dla każdego dodanego wiersza, niezależnie od tego, czy dane są ponownie przesyłane do elementu GridView. Oznacza to, że nawet w przypadku powrotu po ponownym załadowaniu danych ze stanu widoku zdarzenie nadal jest uruchamiane i jest to powód, RowCreated dla którego używamy go zamiast RowDataBound (co jest uruchamiane tylko wtedy, gdy dane są jawnie powiązane z kontrolką sieci Web danych).

W tej procedurze obsługi zdarzeń chcemy kontynuować tylko wtedy, gdy mamy do czynienia z wierszem danych. Dla każdego wiersza danych chcemy programowo odwołać RadioButtonMarkup się do kontrolki Literał i ustawić jej Text właściwość na znaczniki, aby emitować. Jak pokazano w poniższym kodzie, adiustacja emitowana tworzy przycisk radiowy, którego name atrybut jest ustawiony na , którego id atrybut jest ustawiony na SuppliersGroupRowSelectorX, gdzie X jest indeksem wiersza GridView i którego value atrybut jest ustawiony na indeks wiersza GridView.

Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
    Handles Suppliers.RowCreated
    
    If e.Row.RowType = DataControlRowType.DataRow Then
        ' Grab a reference to the Literal control
        Dim output As Literal = _
            CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
        ' Output the markup except for the "checked" attribute
        output.Text = String.Format( _
            "<input type="radio" name="SuppliersGroup" " & _
            "id="RowSelector{0}" value="{0}" />", e.Row.RowIndex)
    End If
End Sub

Gdy zostanie wybrany wiersz GridView i nastąpi powrót, interesuje SupplierID nas wybrany dostawca. W związku z tym można pomyśleć, że wartość każdego przycisku radiowego powinna być rzeczywista SupplierID (a nie indeks wiersza GridView). Chociaż może to działać w pewnych okolicznościach, byłoby to zagrożenie bezpieczeństwa, aby ślepo zaakceptować i przetworzyć element SupplierID. Nasz widok GridView zawiera na przykład listę tylko tych dostawców w USA. Jeśli SupplierID jednak element jest przekazywany bezpośrednio z przycisku radiowego, co zatrzymać złośliwy użytkownik przed manipulowaniem SupplierID wartością wysłaną z powrotem po powrocie? Używając indeksu wiersza jako valueelementu , a następnie pobierania SupplierID po powrocie zwrotne z DataKeys kolekcji, możemy upewnić się, że użytkownik używa tylko jednej z SupplierID wartości skojarzonych z jednym z wierszy GridView.

Po dodaniu tego kodu procedury obsługi zdarzeń poświęć minutę, aby przetestować stronę w przeglądarce. Najpierw należy pamiętać, że jednocześnie można wybrać tylko jeden przycisk radiowy w siatce. Jednak po wybraniu przycisku radiowego i kliknięciu jednego z przycisków następuje powrót, a przyciski radiowe zostaną przywrócone do stanu początkowego (czyli po powrocie, wybrany przycisk radiowy nie jest już zaznaczony). Aby rozwiązać ten problem, musimy rozszerzyć procedurę RowCreated obsługi zdarzeń tak, aby sprawdzała wybrany indeks przycisku radiowego wysłany z poświadczeń zwrotnych i dodaje checked="checked" atrybut do emitowanego adiustacji dopasowań indeksu wierszy.

Po zakończeniu wycofywania przeglądarka wysyła z powrotem name i value wybranego przycisku radiowego. Wartość można pobrać programowo przy użyciu polecenia Request.Form("name"). WłaściwośćRequest.Form zawiera reprezentację NameValueCollection zmiennych formularza. Zmienne formularza to nazwy i wartości pól formularza na stronie internetowej i są wysyłane z powrotem przez przeglądarkę internetową za każdym razem, gdy następuje powrót po powrocie. Ponieważ renderowany name atrybut przycisków radiowych w elemecie GridView to SuppliersGroup, gdy strona internetowa zostanie wysłana z powrotem, przeglądarka zostanie odesłana SuppliersGroup=valueOfSelectedRadioButton do serwera internetowego (wraz z innymi polami formularza). Te informacje można następnie uzyskać z Request.Form właściwości przy użyciu polecenia : Request.Form("SuppliersGroup").

Ponieważ musimy określić wybrany indeks przycisku radiowego nie tylko w RowCreated procedurze obsługi zdarzeń, ale także w Click programach obsługi zdarzeń dla kontrolek Sieci Web przycisków, dodajmy SuppliersSelectedIndex właściwość do klasy za pomocą kodu, która zwraca -1 , jeśli nie wybrano przycisku radiowego i wybrany indeks, jeśli wybrano jeden z przycisków radiowych.

Private ReadOnly Property SuppliersSelectedIndex() As Integer
    Get
        If String.IsNullOrEmpty(Request.Form("SuppliersGroup")) Then
            Return -1
        Else
            Return Convert.ToInt32(Request.Form("SuppliersGroup"))
        End If
    End Get
End Property

Po dodaniu tej właściwości wiemy, aby dodać znaczniki checked="checked" w procedurze RowCreated obsługi zdarzeń, gdy SuppliersSelectedIndex jest równa e.Row.RowIndex. Zaktualizuj procedurę obsługi zdarzeń, aby uwzględnić następującą logikę:

Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
    Handles Suppliers.RowCreated
    
    If e.Row.RowType = DataControlRowType.DataRow Then
        ' Grab a reference to the Literal control
        Dim output As Literal = _
            CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
        ' Output the markup except for the "checked" attribute
        output.Text = String.Format( _
            "<input type="radio" name="SuppliersGroup" " & _
            "id="RowSelector{0}" value="{0}"", e.Row.RowIndex)
        ' See if we need to add the "checked" attribute
        If SuppliersSelectedIndex = e.Row.RowIndex Then
            output.Text &= " checked="checked""
        End If
        ' Add the closing tag
        output.Text &= " />"
    End If
End Sub

Po tej zmianie wybrany przycisk radiowy pozostaje zaznaczony po powłoce. Teraz, gdy mamy możliwość określenia, jaki przycisk radiowy jest zaznaczony, możemy zmienić zachowanie tak, aby po pierwszym odwiedzeniu strony pierwszy przycisk radiowy wiersza GridView został wybrany (zamiast domyślnie nie mieć wybranych przycisków radiowych, co jest bieżącym zachowaniem). Aby domyślnie wybrać pierwszy przycisk radiowy, po prostu zmień instrukcję If SuppliersSelectedIndex = e.Row.RowIndex Then na następującą: If SuppliersSelectedIndex = e.Row.RowIndex OrElse (Not Page.IsPostBack AndAlso e.Row.RowIndex = 0) Then.

W tym momencie dodaliśmy kolumnę pogrupowanych przycisków radiowych do kontrolki GridView, która umożliwia wybranie pojedynczego wiersza kontrolki GridView i zapamiętanie ich po powrocie. Następne kroki to wyświetlenie produktów dostarczonych przez wybranego dostawcę. W kroku 4 zobaczymy, jak przekierować użytkownika do innej strony, wysyłając dane wzdłuż wybranego SupplierIDelementu . W kroku 5 zobaczymy, jak wyświetlić wybrane produkty dostawcy w elemecie GridView na tej samej stronie.

Uwaga

Zamiast używać pola TemplateField (fokus tego długiego kroku 3), możemy utworzyć klasę niestandardową DataControlField , która renderuje odpowiedni interfejs użytkownika i funkcjonalność. KlasaDataControlField jest klasą bazową, z której pochodzą pola BoundField, CheckBoxField, TemplateField i inne wbudowane pola GridView i DetailsView. Utworzenie klasy niestandardowej DataControlField oznaczałoby, że można dodać kolumnę przycisków radiowych tylko przy użyciu składni deklaratywnej, a także znacznie ułatwić replikowanie funkcji na innych stronach internetowych i innych aplikacjach internetowych.

Jeśli kiedykolwiek utworzono niestandardowe, skompilowane kontrolki w ASP.NET, jednak wiesz, że wymaga to dość dużo pracy w nogach i niesie ze sobą wiele subtelności i przypadków krawędzi, które muszą być starannie obsługiwane. W związku z tym będziemy wdrażać kolumnę przycisków radiowych jako klasę niestandardową DataControlField na razie i trzymać się opcji TemplateField. Być może będziemy mieli szansę zapoznać się z tworzeniem, używaniem i wdrażaniem klas niestandardowych DataControlField w przyszłym samouczku.

Krok 4. Wyświetlanie wybranych produktów dostawcy na oddzielnej stronie

Gdy użytkownik wybrał wiersz GridView, musimy wyświetlić wybrane produkty dostawcy. W niektórych okolicznościach możemy chcieć wyświetlić te produkty na osobnej stronie, a inne wolisz to zrobić na tej samej stronie. Najpierw sprawdźmy, jak wyświetlać produkty na osobnej stronie; W kroku 5 przyjrzymy się dodaniu elementu GridView do RadioButtonField.aspx wyświetlania wybranych produktów dostawcy.

Obecnie na stronie ListProducts znajdują się dwie kontrolki sieci Web Przycisk i SendToProducts. Po kliknięciu SendToProducts przycisku chcemy wysłać użytkownika do ~/Filtering/ProductsForSupplierDetails.aspx. Ta strona została utworzona w samouczku Filtrowanie wzorca/szczegółów między dwiema stronami i wyświetla produkty dostawcy, którego SupplierID dane są przekazywane za pośrednictwem pola tworzenia zapytań o nazwie SupplierID.

Aby zapewnić tę funkcję, utwórz procedurę obsługi zdarzeń dla SendToProducts zdarzenia Przycisk Click . W kroku 3 dodaliśmy SuppliersSelectedIndex właściwość, która zwraca indeks wiersza, którego przycisk radiowy jest zaznaczony. Odpowiednie dane SupplierID można pobrać z kolekcji GridView, DataKeys a użytkownik może następnie zostać wysłany do ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID programu przy użyciu polecenia Response.Redirect("url").

Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
    Handles SendToProducts.Click
    
    ' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
    Dim supplierID As Integer = _
        Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
    Response.Redirect( _
        "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
        supplierID)
End Sub

Ten kod działa cudownie, o ile jeden z przycisków radiowych jest wybierany z kontrolki GridView. Jeśli początkowo element GridView nie ma zaznaczonych przycisków radiowych, a użytkownik kliknie SendToProducts przycisk , będzie -1to , SuppliersSelectedIndex co spowoduje zgłoszenie wyjątku, ponieważ -1 jest poza zakresem indeksu DataKeys kolekcji. Nie jest to jednak problem, jeśli zdecydujesz się zaktualizować RowCreated procedurę obsługi zdarzeń zgodnie z opisem w kroku 3, aby początkowo wybrać pierwszy przycisk radiowy w siatce.

Aby uwzględnić SuppliersSelectedIndex wartość elementu -1, dodaj kontrolkę Etykieta sieci Web do strony powyżej kontrolki GridView. IDChooseSupplierMsgUstaw właściwość na , jej CssClass właściwość na Warning, jej EnableViewState właściwości Falsei Visible na , a jej Text właściwość na Wybierz dostawcę z siatki. Klasa Warning CSS wyświetla tekst w czerwonej, kursywie, pogrubionej, dużej czcionki i jest definiowany w pliku Styles.css. Ustawiając EnableViewState właściwości i Visible na False, etykieta nie jest renderowana z wyjątkiem tylko tych poświadczeń, w których właściwość kontrolki Visible jest programowo ustawiona na True.

Dodawanie kontrolki sieci Web etykiety nad kontrolką GridView

Rysunek 13. Dodawanie kontrolki sieci Web etykiety nad kontrolką GridView (kliknij, aby wyświetlić obraz pełnowymiarowy)

Następnie rozszerz procedurę Click obsługi zdarzeń, aby wyświetlić etykietę ChooseSupplierMsg , jeśli SuppliersSelectedIndex jest mniejsza niż zero, i przekieruj użytkownika do ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID innego.

Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
    Handles SendToProducts.Click
    
    ' make sure one of the radio buttons has been selected
    If SuppliersSelectedIndex < 0 Then
        ChooseSupplierMsg.Visible = True
    Else
        ' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
        Dim supplierID As Integer = _
            Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
        Response.Redirect( _
            "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
            supplierID)
    End If
End Sub

Odwiedź stronę w przeglądarce i kliknij SendToProducts przycisk przed wybraniem dostawcy z widoku GridView. Jak pokazano na rysunku 14, zostanie wyświetlona etykieta ChooseSupplierMsg . Następnie wybierz dostawcę i kliknij SendToProducts przycisk. Spowoduje to whisk do strony zawierającej listę produktów dostarczonych przez wybranego dostawcę. Rysunek 15 przedstawia stronę po wybraniu ProductsForSupplierDetails.aspx dostawcy Bigfoot Breweries.

Etykieta ChooseSupplierMsg jest wyświetlana, jeśli nie wybrano dostawcy

Rysunek 14. Etykieta jest wyświetlana ChooseSupplierMsg , jeśli nie wybrano dostawcy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Wybrane produkty dostawcy są wyświetlane w ProductsForSupplierDetails.aspx

Rysunek 15. Wyświetlane ProductsForSupplierDetails.aspx są produkty wybranego dostawcy (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Krok 5. Wyświetlanie wybranych produktów dostawców na tej samej stronie

W kroku 4 pokazano, jak wysłać użytkownika do innej strony internetowej w celu wyświetlenia wybranych produktów dostawców. Alternatywnie wybrane produkty dostawcy mogą być wyświetlane na tej samej stronie. Aby to zilustrować, dodamy kolejny element GridView, aby wyświetlić RadioButtonField.aspx wybrane produkty dostawców.

Ponieważ chcemy, aby ten element GridView produktów był wyświetlany tylko po wybraniu dostawcy, dodaj kontrolkę Panel sieci Web pod Suppliers kontrolką GridView, ustawiając jej ID właściwość na ProductsBySupplierPanel i jej Visible właściwość na False. W panelu dodaj tekst Products for the Selected Supplier (Produkty wybranego dostawcy), a następnie gridView o nazwie ProductsBySupplier. W tagu inteligentnym GridView wybierz powiązanie go z nowym obiektem ObjectDataSource o nazwie ProductsBySupplierDataSource.

Wiązanie elementu ProductsBySupplier GridView z nowym obiektem ObjectDataSource

Rysunek 16. Powiązanie kontrolki ProductsBySupplier GridView z nowym obiektem ObjectDataSource (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Następnie skonfiguruj obiekt ObjectDataSource do używania ProductsBLL klasy . Ponieważ chcemy tylko pobrać te produkty dostarczone przez wybranego dostawcę, określ, że obiekt ObjectDataSource powinien wywołać metodę GetProductsBySupplierID(supplierID) w celu pobrania danych. Wybierz pozycję (Brak) z list rozwijanych na kartach UPDATE, INSERT i DELETE.

Konfigurowanie obiektu ObjectDataSource do używania metody GetProductsBySupplierID(supplierID)

Rysunek 17. Konfigurowanie obiektu ObjectDataSource do użycia GetProductsBySupplierID(supplierID) metody (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Ustaw Drop-Down Listy na wartość (Brak) na kartach UPDATE, INSERT i DELETE

Rysunek 18. Ustawianie Drop-Down Listy na wartość (Brak) na kartach UPDATE, INSERT i DELETE (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po skonfigurowaniu kart SELECT, UPDATE, INSERT i DELETE kliknij przycisk Dalej. GetProductsBySupplierID(supplierID) Ponieważ metoda oczekuje parametru wejściowego, kreator Tworzenia źródła danych monituje nas o określenie źródła dla wartości parametru.

W tym miejscu mamy kilka opcji określania źródła wartości parametru. Możemy użyć domyślnego obiektu Parameter i programowo przypisać wartość SuppliersSelectedIndex właściwości do właściwości Parameter DefaultValue w programie obsługi zdarzeń ObjectDataSource Selecting . Wróć do samouczka Programmatically Setting the ObjectDataSource's Parameter Values (Programowe ustawianie wartości parametrów obiektu ObjectDataSource ), aby odświeżyć moduł do programowego przypisywania wartości do parametrów obiektuDataSource.

Alternatywnie możemy użyć kontrolki ControlParameter i odwołać się do Suppliers właściwości GridView SelectedValue (zobacz Rysunek 19). Właściwość GridView SelectedValue zwraca DataKey wartość odpowiadającą SelectedIndex właściwości . Aby ta opcja działała, musimy programowo ustawić właściwość GridView na SelectedIndex wybrany wiersz po kliknięciu ListProducts przycisku. W ramach dodatkowej SelectedIndexkorzyści ustawienie elementu spowoduje, że wybrany rekord zostanie włączony SelectedRowStyle zgodnie z DataWebControls definicją w motywie (żółtym tle).

Użyj kontrolkiParameter, aby określić wartość SelectedValue kontrolki GridView jako źródło parametru

Rysunek 19. Użyj kontrolkiParameter, aby określić element GridView s SelectedValue jako źródło parametrów (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po ukończeniu pracy kreatora program Visual Studio automatycznie doda pola dla pól danych produktu. Usuń wszystkie elementy ProductName, CategoryNamei UnitPrice BoundFields, a następnie zmień HeaderText właściwości na Product, Category i Price. Skonfiguruj pole BoundField tak UnitPrice , aby jego wartość została sformatowana jako waluta. Po wprowadzeniu tych zmian znaczniki deklaratywne panelowe, GridView i ObjectDataSource powinny wyglądać następująco:

<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
    <h3>
        Products for the Selected Supplier</h3>
    <p>
        <asp:GridView ID="ProductsBySupplier" runat="server" 
            AutoGenerateColumns="False" DataKeyNames="ProductID"
            DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
            <Columns>
                <asp:BoundField DataField="ProductName" HeaderText="Product" 
                    SortExpression="ProductName" />
                <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                    ReadOnly="True" SortExpression="CategoryName" />
                <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
                    HeaderText="Price" HtmlEncode="False" 
                    SortExpression="UnitPrice" />
            </Columns>
        </asp:GridView>
        <asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server" 
            OldValuesParameterFormatString="original_{0}"
            SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
            <SelectParameters>
                <asp:ControlParameter ControlID="Suppliers" Name="supplierID" 
                    PropertyName="SelectedValue" Type="Int32" />
            </SelectParameters>
        </asp:ObjectDataSource>
    </p>
</asp:Panel>

Aby ukończyć to ćwiczenie, należy ustawić właściwość GridView SelectedIndex na SelectedSuppliersIndex właściwość i ProductsBySupplierPanel właściwość Visible Panel na True po kliknięciu ListProducts przycisku. W tym celu utwórz procedurę obsługi zdarzeń dla ListProducts zdarzenia kontrolki Click Sieci Web przycisku i dodaj następujący kod:

Protected Sub ListProducts_Click(sender As Object, e As EventArgs) _
    Handles ListProducts.Click
    
    ' make sure one of the radio buttons has been selected
    If SuppliersSelectedIndex < 0 Then
        ChooseSupplierMsg.Visible = True
        ProductsBySupplierPanel.Visible = False
    Else
        ' Set the GridView's SelectedIndex
        Suppliers.SelectedIndex = SuppliersSelectedIndex
        ' Show the ProductsBySupplierPanel panel
        ProductsBySupplierPanel.Visible = True
    End If
End Sub

Jeśli dostawca nie został wybrany z kontrolki GridView, ChooseSupplierMsg zostanie wyświetlona etykieta i ProductsBySupplierPanel panel ukryty. W przeciwnym razie, jeśli wybrano dostawcę, ProductsBySupplierPanel zostanie wyświetlona wartość , a właściwość GridView zostanie zaktualizowana SelectedIndex .

Rysunek 20 przedstawia wyniki po wybraniu dostawcy Bigfoot Breweries i kliknięciu przycisku Pokaż produkty na stronie.

Produkty dostarczone przez Bigfoot Breweries są wymienione na tej samej stronie

Rysunek 20. Produkty dostarczone przez Bigfoot Breweries są wyświetlane na tej samej stronie (kliknij, aby wyświetlić obraz pełnowymiarowy)

Podsumowanie

Zgodnie z opisem w samouczku Master/Detail Using a Selectable Master GridView with a Details DetailView (Szczegóły) rekordy można wybrać z obiektu GridView przy użyciu kontrolki CommandField, której ShowSelectButton właściwość jest ustawiona na Truewartość . Jednak pole CommandField wyświetla przyciski jako zwykłe przyciski, linki lub obrazy. Alternatywny interfejs użytkownika wyboru wiersza polega na podaniu przycisku radiowego lub pola wyboru w każdym wierszu Kontrolka GridView. W tym samouczku sprawdziliśmy, jak dodać kolumnę przycisków radiowych.

Niestety dodanie kolumny przycisków radiowych nie jest tak proste, jak można się spodziewać. Nie ma wbudowanego elementu RadioButtonField, które można dodać po kliknięciu przycisku, a użycie kontrolki Sieci Web RadioButton w elemecie TemplateField wprowadza własny zestaw problemów. W końcu, aby zapewnić taki interfejs, musimy utworzyć niestandardową DataControlField klasę lub uciekać się do wstrzykiwania odpowiedniego kodu HTML do pola templatefield podczas RowCreated zdarzenia.

Po zapoznaniu się z dodawaniem kolumny przycisków radiowych zwróćmy uwagę na dodanie kolumny pól wyboru. Przy użyciu kolumny pól wyboru użytkownik może wybrać co najmniej jeden wiersz GridView, a następnie wykonać operację na wszystkich zaznaczonych wierszach (na przykład wybranie zestawu wiadomości e-mail z internetowego klienta poczty e-mail, a następnie wybranie usunięcia wszystkich wybranych wiadomości e-mail). W następnym samouczku zobaczymy, jak dodać taką kolumnę.

Szczęśliwe programowanie!

Informacje o autorze

Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została przejrzyona przez wielu przydatnych recenzentów. Głównym recenzentem tego samouczka był David Suru. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresemmitchell@4GuysFromRolla.com .