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

przez Scott Mitchell

Pobierz przykładową aplikację lub Pobierz plik PDF

Ten samouczek rozszerza relację główną/szczegółową, aby dodać trzecią warstwę, przy użyciu dwóch kontrolek DropDownList do wybierania żądanych rekordów nadrzędnych i nadrzędnego.

Wprowadzenie

W poprzednim samouczku sprawdzono sposób wyświetlania prostego raportu wzorzec/szczegóły przy użyciu jednego DropDownList wypełnionego kategoriami i GridView pokazujących te produkty należące do wybranej kategorii. Ten wzorzec raportu działa dobrze, gdy są wyświetlane rekordy, które mają relację "jeden do wielu" i można ją łatwo rozszerzyć na potrzeby scenariuszy obejmujących wiele relacji jeden-do-wielu. Na przykład system wprowadzania zamówień ma tabele, które odpowiadają klientom, zamówieniom i wierszom zamówienia. Dany klient może mieć wiele zamówień z każdą kolejnością składającą się z wielu elementów. Takie dane mogą być prezentowane użytkownikowi przy użyciu dwóch kontrolek DropDownList i GridView. Pierwszy DropDownList będzie miał element listy dla każdego klienta w bazie danych, a druga zawartość jest zamówieniami umieszczonymi przez wybranego klienta. W widoku GridView będą wystawiane elementy wiersza z wybranej kolejności.

Baza danych Northwind zawiera dane kanoniczne dotyczące klienta/zamówienia/zamówienia w tabelach Customers, Ordersi Order Details, ale te tabele nie są przechwytywane w naszej architekturze. Mimo to nadal możemy zilustrować użycie dwóch zależnych kontrolek DropDownList. Pierwszy DropDownList wyświetli listę kategorii, a drugi produkty należące do wybranej kategorii. Następnie w widoku DetailsView zostaną wystawione szczegóły wybranego produktu.

Krok 1. Tworzenie i wypełnianie kategorii DropDownList

Pierwszym celem jest dodanie DropDownList, który zawiera listę kategorii. Te kroki zostały szczegółowo opisane w poprzednim samouczku, ale zostały podsumowane w tym miejscu pod kątem kompletności.

Otwórz stronę MasterDetailsDetails.aspx w folderze Filtering, Dodaj DropDownList do strony, ustaw jej Właściwość ID na Categories, a następnie kliknij link Konfiguruj źródło danych w swoim tagu inteligentnym. W Kreatorze konfiguracji źródła danych wybierz, aby dodać nowe źródło danych.

dodać nowego źródła danych dla DropDownList

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

Nowe źródło danych powinno, naturalnie, być obiektem ObjectDataSource. Nazwij ten nowy element ObjectDataSource CategoriesDataSource i Wywołaj metodę GetCategories() obiektu CategoriesBLL.

wybrać użycie klasy CategoriesBLL

Rysunek 2. wybór użycia klasy CategoriesBLL (kliknij,Aby wyświetlić obraz w pełnym rozmiarze)

skonfigurować element ObjectDataSource do korzystania z metody GetCategories ()

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

Po skonfigurowaniu elementu ObjectDataSource nadal musimy określić, które pole źródła danych ma być wyświetlane w Categories DropDownList i który ma być skonfigurowany jako wartość dla elementu listy. Ustaw CategoryName pole jako wartość wyświetlaną i CategoryID jako wartości dla każdego elementu listy.

wyświetlać DropDownList pole CategoryName i używać IDkategorii jako wartości

Rysunek 4. DropDownList wyświetlić pola CategoryName i użyj CategoryID jako wartości (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

W tym momencie mamy kontrolkę DropDownList (Categories), która jest wypełniana rekordami z tabeli Categories. Gdy użytkownik wybierze nową kategorię z DropDownList, będziemy mieć ogłaszanie zwrotne w celu odświeżenia DropDownList produktu, które zostaną utworzone w kroku 2. W związku z tym zaznacz opcję Włącz autoogłaszanie w tagu inteligentnym categories DropDownList.

włączyć funkcję autoogłaszania zwrotnego dla kategorii DropDownList

Rysunek 5. Włączanie autoogłaszania zwrotnego dla Categories DropDownList (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Krok 2. Wyświetlanie produktów wybranej kategorii w drugim DropDownList

Po zakończeniu Categories DropDownList, następnym krokiem jest wyświetlenie DropDownList produktów należących do wybranej kategorii. Aby to osiągnąć, Dodaj kolejną DropDownList do strony o nazwie ProductsByCategory. Podobnie jak w przypadku Categories DropDownList, Utwórz nowy element ObjectDataSource dla ProductsByCategory DropDownList o nazwie ProductsByCategoryDataSource.

dodać nowego źródła danych dla ProductsByCategory DropDownList

Ilustracja 6. Dodawanie nowego źródła danych dla ProductsByCategory DropDownList (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

utworzyć nowego elementu ObjectDataSource o nazwie ProductsByCategoryDataSource

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

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

wybrać użycie klasy ProductsBLL

Ilustracja 8. wybór użycia klasy ProductsBLL (kliknij,Aby wyświetlić obraz w pełnym rozmiarze)

skonfigurować element ObjectDataSource do używania metody GetProductsByCategoryID (IDKategorii)

Ilustracja 9. Konfigurowanie elementu ObjectDataSource do używania metody GetProductsByCategoryID(categoryID) (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 Categories DropDownList.

ściągnąć wartość parametru IDKategorii z kategorii DropDownList

Ilustracja 10. ściąganie wartości parametru categoryID z Categories DropDownList (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Po skonfigurowaniu elementu ObjectDataSource wszystkie pozostałe, które pozostają, określają, które pola źródła danych są używane do wyświetlania i wartości elementów DropDownList. Wyświetl ProductName pola i użyj pola ProductID jako wartości.

określić pola źródła danych używane dla właściwości "text i value" elementu "DropDownList".

Ilustracja 11. Określ pola źródła danych używane dla Text DropDownList ListItem s i właściwości Value (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Za pomocą elementów ObjectDataSource i ProductsByCategory skonfigurowanych na naszej stronie zostanie wyświetlonych dwa kontrolek DropDownList: pierwsza spowoduje wyświetlenie listy wszystkich kategorii, a druga spowoduje wyświetlenie listy tych produktów należących do wybranej kategorii. Gdy użytkownik wybierze nową kategorię z pierwszego DropDownListu, odświeżenie zostanie nastąpi, a druga DropDownList zostanie odwiązana, pokazując te produkty należące do nowo wybranej kategorii. Rysunki 12 i 13 pokazują MasterDetailsDetails.aspx w akcji podczas przeglądania za pomocą przeglądarki.

podczas pierwszego odwiedzania strony wybrano kategorię napoje

Rysunek 12. podczas pierwszego odwiedzania strony jest wybierana Kategoria napoje (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

wybranie innej kategorii spowoduje wyświetlenie produktów nowej kategorii

Ilustracja 13. wybranie innej kategorii powoduje wyświetlenie produktów nowej kategorii (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Obecnie productsByCategory DropDownList, gdy zmiana nie powoduje odświeżenia. Będziemy jednak chcieć ogłaszać zwrotne po dodaniu widoku DetailsView, aby wyświetlić szczegółowe informacje o wybranym produkcie (krok 3). W związku z tym zaznacz pole wyboru Włącz autoogłaszanie w tagu inteligentnym productsByCategory DropDownList.

włączyć funkcję autoogłaszania zwrotnego dla productsByCategory DropDownList

Ilustracja 14. Włączanie funkcji autoogłaszania dla productsByCategory DropDownList (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Krok 3. Wyświetlanie szczegółowych informacji o wybranym produkcie przy użyciu widoku DetailsView

Ostatnim krokiem jest wyświetlenie szczegółowych informacji o wybranym produkcie w widoku DetailsView. Aby to osiągnąć, Dodaj do strony opcję DetailsView, ustaw jej Właściwość ID na ProductDetailsi Utwórz dla niej nowy element ObjectDataSource. Skonfiguruj ten element ObjectDataSource do ściągania danych z metody GetProductByProductID(productID) klasy ProductsBLL przy użyciu wybranej wartości ProductsByCategory DropDownList dla wartości parametru productID .

wybrać użycie klasy ProductsBLL

Ilustracja 15. Wybierz, aby użyć klasy ProductsBLL (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

skonfigurować element ObjectDataSource do korzystania z metody GetProductByProductID (productID)

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

ściągnąć wartość parametru productID z ProductsByCategory DropDownList

Ilustracja 17. ściąganie wartości parametru productID z ProductsByCategory DropDownList (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Możesz wybrać opcję wyświetlania dowolnego z dostępnych pól w widoku DetailsView. Wybrano, aby usunąć pola ProductID, SupplierIDi CategoryID oraz zmienić ich kolejność i sformatować pozostałe pola. Dodatkowo wyczyściłem Height i Width właściwości, co pozwala na rozwijanie widoku DetailsView do szerokości wymaganej do najlepszego wyświetlenia danych, a nie ograniczenia do określonego rozmiaru. Pełny znacznik jest widoczny poniżej:

<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>

Zapoznaj się z chwilą, aby wypróbować stronę MasterDetailsDetails.aspx w przeglądarce. Na pierwszy rzut oka może się wydawać, że wszystko działa zgodnie z potrzebami, ale wystąpił delikatny problem. Po wybraniu nowej kategorii ProductsByCategory DropDownList zostanie zaktualizowana w celu uwzględnienia tych produktów dla wybranej kategorii, ale ProductDetails DetailsView nadal będzie pokazywała poprzednie informacje o produkcie. W przypadku wybrania innego produktu dla wybranej kategorii jest aktualizowana wartość DetailsView. Ponadto, jeśli testujesz dokładnie tyle, że w przypadku ciągłego wybierania nowych kategorii (takich jak wybór napojów z Categories DropDownList, a następnie Przypraws, a następnie wyrobów cukierniczych) każdy inny wybór kategorii spowoduje odświeżenie ProductDetails DetailsView.

Aby pomóc w skonkretyzować tego problemu, przyjrzyjmy się konkretnemu przykładowi. Po pierwszej wizycie na stronie wybrano kategorię napoje i powiązane produkty są ładowane do ProductsByCategory DropDownList. Chai to wybrany produkt, a jego szczegóły są wyświetlane w ProductDetails DetailsView, jak pokazano na rysunku 18.

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

Ilustracja 18. szczegóły wybranego produktu są wyświetlane w widoku DetailsView (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Jeśli zmienisz wybór kategorii z napojów na przyprawy, nastąpi odświeżenie, a ProductsByCategory DropDownList zostanie odpowiednio zaktualizowany, ale w widoku DetailsView nadal będą wyświetlane szczegółowe informacje o Chai.

informacje o poprzednio wybranym produkcie są nadal wyświetlane

Ilustracja 19. szczegóły poprzednio wybranego produktu są nadal wyświetlane (kliknij,Aby wyświetlić obraz o pełnym rozmiarze)

Wybranie nowego produktu z listy spowoduje odświeżenie widoku DetailsView zgodnie z oczekiwaniami. W przypadku wybrania nowej kategorii po zmianie produktu widok DetailsView ponownie nie zostanie odświeżony. Jednak w przypadku wybrania nowego produktu, który został wybrany nowej kategorii, można odświeżyć widok DetailsView. Co na świecie odbywa się tutaj?

Problem dotyczy cyklu życia strony. Za każdym razem, gdy zażądano strony, przejdzie ona przez kilka kroków w miarę renderowania. W jednym z tych kroków kontrolki elementu ObjectDataSource sprawdzają, czy dowolna z wartości SelectParameters uległy zmianie. Jeśli tak, formant sieci Web danych powiązany z elementem ObjectDataSource wie, że musi odświeżyć jego ekran. Na przykład po wybraniu nowej kategorii element ObjectDataSource ProductsByCategoryDataSource wykrył, że jego wartości parametrów uległy zmianie, a ProductsByCategory DropDownList rebind same, pobierając produkty dla wybranej kategorii.

Problem występujący w tej sytuacji polega na tym, że punkt w cyklu życia strony, który sprawdza zmiany parametrów, występuje przed ponownym wiązaniem skojarzonych kontrolek sieci Web danych. W związku z tym podczas wybierania nowej kategorii element ObjectDataSource ProductsByCategoryDataSource wykrywa zmianę wartości parametru. Element ObjectDataSource używany przez ProductDetails DetailsView nie zanotuje żadnych zmian, ponieważ ProductsByCategory DropDownList nie zostały jeszcze oddzielone. W dalszej części cyklu życia ProductsByCategory DropDownList ponownie powiązania z jego elementem ObjectDataSource, co umożliwia przechwyconie produktów dla nowo wybranej kategorii. Gdy wartość ProductsByCategory DropDownList została zmieniona, element ObjectDataSource ProductDetails DetailsView już zrobił sprawdzanie wartości parametrów; w związku z tym, DetailsView wyświetla poprzednie wyniki. Ta interakcja jest przedstawiana na rysunku 20.

zmiany wartości ProductsByCategory DropDownList po przeprowadzeniu testów elementu ObjectDataSource ProductDetails DetailsView dla zmian

Ilustracja 20: wartość ProductsByCategory DropDownList ulega zmianie po ProductDetails sprawdzenia elementu ObjectDataSource w widoku DetailsView dla zmian (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Aby rozwiązać ten konieczność, należy jawnie ponownie powiązać ProductDetails DetailsView po powiązaniu ProductsByCategory DropDownList. Możemy to osiągnąć przez wywołanie metody DataBind() ProductDetails DetailsView, gdy zostanie wyzwolone zdarzenie DataBound ProductsByCategory. Dodaj następujący kod obsługi zdarzeń do klasy związanej z kodem MasterDetailsDetails.aspx strony (zobacz "programowo Ustawianie wartości parametrów elementu ObjectDataSource" w przypadku dyskusji na temat dodawania obsługi zdarzeń):

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

Po dodaniu tego jawnego wywołania metody DataBind() ProductDetails DetailsView, samouczek działa zgodnie z oczekiwaniami. Rysunek 21 przedstawia, w jaki sposób zmiana ta została zmieniona z powodu wcześniejszego problemu.

ProductDetails DetailsView jest jawnie odświeżany, gdy wyzwalane jest zdarzenie powiązane z danymi DropDownList ProductsByCategory

Rysunek 21. ProductDetails DetailsView jest jawnie odświeżany po wypełnieniu zdarzenia DataBound ProductsByCategory DropDownList (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Podsumowanie

DropDownList służy jako idealny element interfejsu użytkownika dla raportów wzorzec/szczegóły, gdy istnieje relacja jeden do wielu między rekordem głównym i szczegółowymi. W poprzednim samouczku przedstawiono sposób użycia jednego DropDownList do filtrowania produktów wyświetlanych przez wybraną kategorię. W tym samouczku zamieniłem GridView produktów na DropDownList i użyto widoku DetailsView, aby wyświetlić szczegóły wybranego produktu. Koncepcje omówione w tym samouczku można łatwo rozszerzyć do modeli danych obejmujących wiele relacji jeden-do-wielu, takich jak klienci, zamówienia i elementy zamówienia. Ogólnie rzecz biorąc, można zawsze dodać DropDownList dla każdej jednostki "jednego" w relacji jeden-do-wielu.

Szczęśliwe programowanie!

Informacje o autorze

Scott Mitchell, autor siedmiu grup ASP/ASP. NET Books i założyciel of 4GuysFromRolla.com, pracował z technologiami sieci Web firmy Microsoft od czasu 1998. Scott działa jako niezależny konsultant, trainer i składnik zapisywania. Jego Najnowsza książka to Sams ASP.NET 2,0 w ciągu 24 godzin. Można go osiągnąć w mitchell@4GuysFromRolla.com. lub za pośrednictwem swojego blogu, który można znaleźć w http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została sprawdzona przez wielu przydatnych recenzentów. Recenzent potencjalnych klientów dla tego samouczka został Hilton Giesenow. Chcesz przeglądać moje nadchodzące artykuły MSDN? Jeśli tak, upuść mi linię w mitchell@4GuysFromRolla.com.