Filtrowanie rekordu głównego/szczegółów przy użyciu dwóch kontrolek DropDownList (C#)

Autor : Scott Mitchell

Pobierz plik PDF

Ten samouczek rozszerza relację wzorca/szczegółów w celu dodania trzeciej warstwy przy użyciu dwóch kontrolek DropDownList w celu wybrania żądanych rekordów nadrzędnych i dziadków.

Wprowadzenie

W poprzednim samouczku zbadaliśmy sposób wyświetlania prostego raportu głównego/szczegółów przy użyciu pojedynczej listy DropDownList wypełnionej kategoriami i kontrolką GridView pokazującą te produkty, które należą do wybranej kategorii. Ten wzorzec raportu działa dobrze podczas wyświetlania rekordów, które mają relację jeden do wielu i można je łatwo rozszerzyć w celu pracy w scenariuszach obejmujących wiele relacji jeden do wielu. Na przykład system wprowadzania zamówień będzie miał tabele, które odpowiadają klientom, zamówieniam i elementom wiersza zamówienia. Dany klient może mieć wiele zamówień z każdym zamówieniem składającym się z wielu elementów. Takie dane mogą być prezentowane użytkownikowi z dwoma listami DropDownList i GridView. Pierwsza lista DropDownList zawierałaby element listy dla każdego klienta w bazie danych z zawartością drugiego klienta, która jest zamówieniami złożonymi przez wybranego klienta. Obiekt GridView wyświetli listę elementów wiersza z wybranej kolejności.

Baza danych Northwind zawiera kanoniczne informacje o danych klienta/zamówienia/zamówienia w tabelach Customers, Ordersi Order Details , ale te tabele nie są przechwytywane w naszej architekturze. Niemniej jednak nadal możemy zilustrować użycie dwóch zależnych list DropDownList. Pierwsza lista rozwijana będzie zawierać kategorie, a drugie produkty należące do wybranej kategorii. Element DetailsView wyświetli następnie szczegóły wybranego produktu.

Krok 1. Tworzenie i wypełnianie listy rozwijanej KategorieLista

Naszym pierwszym celem jest dodanie listy DropDownList zawierającej kategorie. Te kroki zostały szczegółowo zbadane w poprzednim samouczku, ale zostały tutaj podsumowane pod kątem kompletności.

MasterDetailsDetails.aspx Otwórz stronę w folderzeFiltering, dodaj listę DropDownList do strony, ustaw jej ID właściwość na Categories, a następnie kliknij link Konfiguruj źródło danych w tagu inteligentnym. W Kreatorze konfiguracji źródła danych wybierz opcję dodania nowego źródła danych.

Dodawanie nowego źródła danych dla listy rozwijanej

Rysunek 1. Dodawanie nowego źródła danych dla listy rozwijanej (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Nowe źródło danych powinno być oczywiście obiektem ObjectDataSource. Nadaj tej nowej nazwie obiekt ObjectDataSource CategoriesDataSource i wywołaj metodę CategoriesBLLGetCategories() obiektu.

Wybierz, aby użyć klasy CategoriesBLL

Rysunek 2. Wybierz opcję użycia CategoriesBLL klasy (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Konfigurowanie obiektu ObjectDataSource do używania metody GetCategories()

Rysunek 3. Konfigurowanie obiektu ObjectDataSource do użycia GetCategories() metody (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po skonfigurowaniu obiektu ObjectDataSource nadal musimy określić, które pole źródła danych powinno być wyświetlane w polu Categories Lista rozwijana i które należy skonfigurować jako wartość elementu listy. CategoryName Ustaw pole jako wyświetlane i CategoryID jako wartość dla każdego elementu listy.

Wyświetl pole CategoryName i użyj wartości CategoryID jako wartości listy rozwijanej Lista rozwijana

Rysunek 4. Wyświetlanie pola Lista rozwijanaLista CategoryName i użycie CategoryID jako wartości (kliknij, aby wyświetlić obraz pełnowymiarowy)

W tym momencie mamy kontrolkę DropDownList (Categories), która jest wypełniana rekordami z Categories tabeli. Gdy użytkownik wybierze nową kategorię z listy RozwijanejList, chcemy, aby powrót został wyświetlony, aby odświeżyć listę rozwijaną produktu, którą utworzymy w kroku 2. W związku z tym sprawdź opcję Włącz autopostback z tagu inteligentnego categories DropDownList.

Włącz autopostback dla listy rozwijanej Kategorii

Rysunek 5. Włączanie funkcji AutoPostBack dla listy rozwijanej Categories (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Krok 2. Wyświetlanie produktów wybranej kategorii na drugiej liście rozwijanej

Po zakończeniu listy Categories DropDownList następnym krokiem jest wyświetlenie listy rozwijanej produktów należących do wybranej kategorii. Aby to osiągnąć, dodaj kolejną listę DropDownList do strony o nazwie ProductsByCategory. Podobnie jak w przypadku listy Categories DropDownList, utwórz nową wartość ObjectDataSource dla listy ProductsByCategory DropDownList o nazwie ProductsByCategoryDataSource.

Dodawanie nowego źródła danych dla listy rozwijanej ProductsByCategory

Rysunek 6. Dodawanie nowego źródła danych dla listy rozwijanej ProductsByCategory (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Tworzenie nowego obiektuDataSource o nazwie ProductsByCategoryDataSource

Rysunek 7. Tworzenie nowego obiektuDataSource o nazwie ProductsByCategoryDataSource (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Ponieważ lista ProductsByCategory DropDownList musi wyświetlać tylko te produkty należące do wybranej kategorii, obiekt ObjectDataSource wywołuje metodę GetProductsByCategoryID(categoryID) z ProductsBLL obiektu .

Zrzut ekranu przedstawiający okno Konfiguruj źródło danych — productsByCategoryDataSource z wybraną wartością ProductsBLL i wyróżnionym przyciskiem Next (Dalej).

Rysunek 8. Wybierz opcję użycia ProductsBLL klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Konfigurowanie obiektu ObjectDataSource do używania metody GetProductsByCategoryID(categoryID)

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

W ostatnim kroku kreatora musimy określić wartość parametru categoryID . Przypisz ten parametr do wybranego elementu z listy Rozwijanej Categories .

Ściąganie wartości parametru categoryID z listy rozwijanej Kategorii

Rysunek 10. Ściąganie wartości parametru categoryID z listy rozwijanej Categories (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po skonfigurowaniu obiektu ObjectDataSource wystarczy określić, jakie pola źródła danych są używane do wyświetlania i wartości elementów listy Rozwijanej. ProductName Wyświetl pole i użyj ProductID pola jako wartości.

Określanie pól źródła danych używanych dla właściwości tekstowych i wartości listitems listy rozwijanej

Rysunek 11. Określanie pól źródła danych używanych dla właściwości i Value listy rozwijanej (ListItemTextkliknij, aby wyświetlić obraz pełnowymiarowy)

Po skonfigurowaniu obiektu ObjectDataSource i ProductsByCategory DropDownList na naszej stronie zostaną wyświetlone dwie listy Listy rozwijane: pierwsza będzie zawierać listę wszystkich kategorii, podczas gdy druga będzie zawierać te produkty należące do wybranej kategorii. Gdy użytkownik wybierze nową kategorię z pierwszej listy DropDownList, zostanie wyświetlony komunikat zwrotny, a druga lista DropDownList zostanie odbicia, pokazując te produkty należące do nowo wybranej kategorii. Ilustracje 12 i 13 są wyświetlane MasterDetailsDetails.aspx w akcji po wyświetleniu w przeglądarce.

Podczas pierwszej wizyty na stronie wybrano kategorię Napoje

Rysunek 12. Podczas pierwszej wizyty na stronie wybrana jest kategoria napojów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Wybranie innej kategorii powoduje wyświetlenie produktów nowej kategorii

Rysunek 13. Wybranie innej kategorii wyświetla produkty nowej kategorii (kliknij, aby wyświetlić obraz pełnowymiarowy)

Obecnie lista productsByCategory DropDownList, gdy została zmieniona, nie powoduje ogłaszania zwrotnego. Jednak po dodaniu elementu DetailsView do wyświetlenia szczegółów wybranego produktu (krok 3) chcemy, aby powrót po dodaniu elementu DetailsView został wyświetlony. W związku z tym zaznacz pole wyboru Włącz autopostback z tagu inteligentnego productsByCategory Listy rozwijanej.

Włączanie funkcji AutoPostBack dla elementów productsByCategory DropDownList

Rysunek 14. Włączanie funkcji AutoPostBack dla listy rozwijanej productsByCategory (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Krok 3. Wyświetlanie szczegółów dla wybranego produktu za pomocą kontrolki DetailsView

Ostatnim krokiem jest wyświetlenie szczegółów wybranego produktu w obiekcie DetailsView. Aby to zrobić, dodaj element DetailsView do strony, ustaw jej ID właściwość na ProductDetails, a następnie utwórz dla niej nową właściwość ObjectDataSource. Skonfiguruj tę wartość ObjectDataSource, aby ściągnąć dane z metody klasy GetProductByProductID(productID) przy użyciu wybranej wartości ProductsByCategory listy DropDownList dla wartości parametruproductID.ProductsBLL

Zrzut ekranu przedstawiający okno Configure Data Source - productsByCategoryDataSource (Konfiguruj źródło danych — productsByCategoryDataSource), w którym wybrano pozycję ProductsBLL i wyróżniono przycisk Next (Dalej).

Rysunek 15. Wybierz opcję użycia ProductsBLL klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Konfigurowanie obiektu ObjectDataSource do używania metody GetProductByProductID(productID)

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

Ściąganie wartości parametru productID z listy rozwijanej ProductsByCategory

Rysunek 17. Ściąganie wartości parametru productID z listy rozwijanej ProductsByCategory (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

W widoku DetailsView można wyświetlić dowolne z dostępnych pól. Zdecydowałem się usunąć ProductIDpola , SupplierIDi CategoryID oraz zmienić kolejność i sformatować pozostałe pola. Ponadto wyczyszczone właściwości kontrolki HeightWidth DetailsView, dzięki czemu element DetailsView może rozwinąć się do szerokości potrzebnej do najlepszego wyświetlania danych, zamiast ograniczać go do określonego rozmiaru. Poniżej zostanie wyświetlona pełna adiustacja:

<asp:DetailsView ID="ProductDetails" runat="server"
    AutoGenerateRows="False" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" EnableViewState="False">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="Product" SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName"
          HeaderText="Category" ReadOnly="True"
          SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName"
          HeaderText="Supplier" ReadOnly="True"
          SortExpression="SupplierName" />
        <asp:BoundField DataField="QuantityPerUnit"
          HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice"
          DataFormatString="{0:c}" HeaderText="Price"
          HtmlEncode="False" SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock"
          HeaderText="UnitsInStock" SortExpression="Units In Stock" />
        <asp:BoundField DataField="UnitsOnOrder"
          HeaderText="UnitsOnOrder" SortExpression="Units On Order" />
        <asp:BoundField DataField="ReorderLevel"
          HeaderText="ReorderLevel" SortExpression="Reorder Level" />
        <asp:CheckBoxField DataField="Discontinued"
          HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

Poświęć chwilę, aby wypróbować MasterDetailsDetails.aspx stronę w przeglądarce. Na pierwszy rzut oka może się wydawać, że wszystko działa zgodnie z potrzebami, ale istnieje subtelny problem. Po wybraniu nowej kategorii ProductsByCategory lista DropDownList zostanie zaktualizowana w celu uwzględnienia tych produktów dla wybranej kategorii, ale kontrolka ProductDetails DetailsView nadal wyświetla poprzednie informacje o produkcie. Element DetailsView jest aktualizowany podczas wybierania innego produktu dla wybranej kategorii. Ponadto, jeśli testujesz wystarczająco dużo, przekonasz się, że jeśli stale wybierasz nowe kategorie (takie jak wybór napojów z Categories listy RozwijanejList, a następnie Condiments, a następnie Confections) każdy inny wybór kategorii powoduje ProductDetails odświeżenie widoku DetailsView.

Aby ułatwić konkretyzację tego problemu, przyjrzyjmy się konkretnemu przykładowi. Po pierwszym otwarciu strony zostanie wybrana kategoria Napoje, a powiązane produkty zostaną załadowane do listy RozwijanejList ProductsByCategory . Chai jest wybranym produktem, a jego szczegóły są wyświetlane w widoku DetailsView, jak pokazano na rysunku ProductDetails 18.

Szczegóły wybranego produktu są wyświetlane w widoku DetailsView

Rysunek 18. Szczegóły wybranego produktu są wyświetlane w widoku Szczegółów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jeśli zmienisz wybór kategorii z Beverages na Condiments, nastąpi ogłaszanie zwrotne, a lista ProductsByCategory DropDownList zostanie odpowiednio zaktualizowana, ale widok DetailsView nadal wyświetla szczegóły dotyczące chai.

Szczegóły wcześniej wybranego produktu są nadal wyświetlane

Rysunek 19. Szczegóły wcześniej wybranego produktu są nadal wyświetlane (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Wybranie nowego produktu z listy odświeża widok DetailsView zgodnie z oczekiwaniami. Jeśli wybierzesz nową kategorię po zmianie produktu, kontrolka DetailsView ponownie nie zostanie odświeżona. Jeśli jednak zamiast wybrania nowego produktu wybrano nową kategorię, widok DetailsView zostanie odświeżyny. Co dzieje się tutaj na świecie?

Problem polega na problemie z chronometrażem w cyklu życia strony. Za każdym razem, gdy zostanie zażądana strona, przejdzie ona przez kilka kroków podczas renderowania. W jednym z tych kroków kontrolki ObjectDataSource sprawdzają, czy którakolwiek z ich SelectParameters wartości uległa zmianie. Jeśli tak, kontrolka internetowa danych powiązana z obiektem ObjectDataSource wie, że musi odświeżyć jego ekran. Na przykład po wybraniu nowej kategorii element ObjectDataSource wykryje, ProductsByCategoryDataSource że jego wartości parametrów uległy zmianie, a ProductsByCategory lista DropDownList ponownie połączy się, uzyskując produkty dla wybranej kategorii.

Problem, który pojawia się w tej sytuacji, polega na tym, że punkt w cyklu życia strony sprawdza, czy obiekt ObjectDataSources pod kątem zmienionych parametrów występuje przed ponownym powiązaniem skojarzonych kontrolek sieci Web danych. W związku z tym podczas wybierania nowej kategorii ProductsByCategoryDataSource element ObjectDataSource wykrywa zmianę wartości parametru. Obiekt ObjectDataSource używany przez ProductDetails element DetailsView nie zanotuje jednak żadnych takich zmian, ponieważ lista ProductsByCategory DropDownList nie została jeszcze odbicia. W dalszej części cyklu życia ProductsByCategory lista DropDownList ponownie połączy się z obiektem ObjectDataSource, chwytając produkty dla nowo wybranej kategorii. ProductsByCategory Chociaż wartość listy DropDownList została zmieniona, ProductDetails funkcja ObjectDataSource obiektu DetailsView wykonała już sprawdzanie wartości parametru, w związku z czym kontrolka DetailsView wyświetla poprzednie wyniki. Ta interakcja jest przedstawiona na rysunku 20.

Wartość ProductsByCategory DropDownList zmienia się po sprawdzeniu przez element ObjectDataSource kontrolki ProductDetails DetailsView pod kątem zmian

Rysunek 20. ProductsByCategory Wartość DropDownList zmienia się po ProductDetails sprawdzeniu właściwości ObjectDataSource kontrolki DetailsView pod kątem zmian (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Aby rozwiązać ten problem, musimy jawnie ponownie ProductDetails powiązać element DetailsView po powiązaniu listy ProductsByCategory DropDownList. Możemy to zrobić, wywołując ProductDetails metodę DetailsView DataBind() , gdy ProductsByCategory zdarzenie DropDownList jest DataBound uruchamiane. Dodaj następujący kod procedury obsługi zdarzeń do MasterDetailsDetails.aspx klasy za pomocą kodu strony (zapoznaj się z tematem "Programowe ustawianie wartości parametrów obiektu ObjectDataSource", aby zapoznać się z omówieniem sposobu dodawania procedury obsługi zdarzeń):

protected void ProductsByCategory_DataBound(object sender, EventArgs e)
{
    ProductDetails.DataBind();
}

Po dodaniu tego jawnego wywołania metody ProductDetails DetailsView DataBind() samouczek działa zgodnie z oczekiwaniami. Rysunek 21 przedstawia sposób rozwiązania tego wcześniejszego problemu.

Element ProductDetails DetailsView jest jawnie odświeżany po uruchomieniu zdarzenia databound listy rozwijanej ProductsByCategoryList

Rysunek 21. Kontrolka ProductDetails DetailsView jest jawnie odświeżona po ProductsByCategory uruchomieniu zdarzenia listy rozwijanej DataBound (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Podsumowanie

Lista DropDownList służy jako idealny element interfejsu użytkownika dla raportów głównych/szczegółowych, w których istnieje relacja jeden do wielu między rekordami głównymi i szczegółowymi. W poprzednim samouczku pokazano, jak używać pojedynczej listy Rozwijanej do filtrowania produktów wyświetlanych przez wybraną kategorię. W tym samouczku zastąpiliśmy kontrolkę GridView produktów listą DropDownList i użyliśmy kontrolki DetailsView, aby wyświetlić szczegóły wybranego produktu. Koncepcje omówione w tym samouczku można łatwo rozszerzyć na modele danych obejmujące wiele relacji jeden do wielu, takich jak klienci, zamówienia i elementy zamówień. Ogólnie rzecz biorąc, zawsze można dodać listę DropDownList dla każdej z jednostek "jeden" w relacjach jeden do wielu.

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ł Hilton Giesenow. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresemmitchell@4GuysFromRolla.com .