TWORZENIE APLIKACJI DLA PRZEDSIĘBIORSTW W VISUAL STUDIO 2010
Opr. st. wykł. mgr inż. Janusz Czuchnowski
na podstawie
Lars Powers, Mike Snell; „Microsoft Visual Studio 2010 Księga Eksperta”; Helion 2009
TWORZENIE APLIKACJI ASP.NET
Nie dotyczy
TWORZENIE APLIKACJI OPARTYCH NA FORMULARZACH WINDOWS
Jednym z głównych celów Visual Studio jest umożliwienie szybkiego konstruowania formularzy Windows (Windows Forms). W niniejszym rozdziale korzystamy z edytora formularzy, panelu Toolbox oraz różnorodnych kontrolek dostarczanych z .NET Framework, rozdział stanowi więc przewodnik po tworzeniu bogatych aplikacji metodą „przeciągnij i upuść". Szczególnie przyjrzymy się, jak najlepiej wykorzystać wbudowane możliwości edytora formularzy oraz systemu projektów Visual Studio do szybkiego budowania formularzy od podstaw.
Nie będziemy się tu troszczyć o kod poza formularzem. Zamiast tego skupimy się na interfejsie użytkownika i zawartych w Visual Studio możliwościach RAD (Rapid Application Development) edytora formularzy. Innymi słowy, skupimy się na możliwościach projektowania IDE, a nie na możliwości oprogramowania formularza i klas kontrolek.
PODSTAWY PROJEKTOWANIA FORMULARZY
Projektowanie odpowiedniego interfejsu użytkownika dla aplikacji Windows jest ciągle połączeniem nauki i sztuki. W świecie formularzy Windows interfejs użytkownika jest zbiorem współpracujących ze sobą obrazów, kontrolek i elementów okien. Użytkownicy przyjmują informacje za pośrednictwem UI i używają go jako podstawowego środka interakcji z aplikacją.
Zadaniem stojącym przed każdym programistą podczas tworzenia interfejsu użytkownika jest przede wszystkim zachowanie równowagi pomiędzy łatwością projektowania a funkcjami, które aplikacja musi udostępniać. Ponadto ważna jest koncepcja standardów zarówno formalnych, jak i doświadczalnych.
Uwaga:
Chociaż używamy tu terminu programista, większość procesu projektowania i planowania UI należy w rzeczywistości do projektanta. Chociaż wiele zespołów nie ma luksusu zatrudniania na pełny etat projektanta UI (jego obowiązki przejmują programiści), to coraz częściej firmy programistyczne starają się pokonać konkurencję, wyróżniając swoje aplikacje za pomocą wyglądu i sposobu obsługi.
Uwzględnianie użytkownika końcowego
Po prostu nie można rozpocząć projektowania przed zrozumieniem sposobu używania aplikacji oraz określeniem jej grupy docelowej. Nawet w przypadku aplikacji zawierających podobne zbiory funkcjonalności konieczne może być uwzględnienie znacznie różniących się doświadczeń użytkowników. Aplikacja zaprojektowana do przechowywania informacji medycznych może mieć te same dane i funkcje, ale będzie różnić się w zależności od tego, czy jest zaprojektowana dla przeciętnego pacjenta, czy też lekarza lub pielęgniarki.
Przypadki użycia i studia ergonomii są doskonałą pomocą w zrozumieniu oczekiwań użytkowników i dostarczają wiedzy pozwalającej na zachowanie równowagi pomiędzy funkcjonalnością a prostotą projektu.
Lokalizacja i kultura
Lokalizacja i kultura także wchodzą w skład tego równania. Typowy formularz aplikacji używanej w USA będzie odpowiadał wymaganiom tej kultury, takim jak przyzwyczajenie do czytania od lewej do prawej i z góry na dół. W tym środowisku najważniejsze elementy UI będą typowo umieszczone w najważniejszej pozycji: lewym górnym rogu formularza. Inne kultury będą wymagać zmiany tej strategii, bazując na zwyczajach czytania od prawej do lewej, a nawet z dołu do góry.
Większość kontrolek w Visual Studio 2008 bezpośrednio wspiera języki, które są czytane od prawej do lewej, za pomocą właściwości RightToLeft. Ustawiając tę właściwość na odpowiednią wartość typu wyliczeniowego RightToLeft, można wskazać, czy tekst kontrolki ma się pojawiać od lewej do prawej, od prawej do lewej, czy też zgodnie z ustawieniami kontrolki macierzystej. Nawet klasa Form wspiera tę właściwość.
Oprócz właściwości RightToLeft niektóre kontrolki udostępniają także właściwość RightToLeftLayout. Ustawienie tej właściwości typu Boolean wpłynie na ogólny układ kontrolki. Przykładowo, ustawienie RightToLeft na True dla obiektu klasy Form spowoduje lustrzane odbicie zawartości formularza.
Wskazówka:
Więcej informacji na temat projektowania aplikacji dla międzynarodowych klientów można znaleźć w MSDN pod hasłem „Best Practices for Deyeloping World-Ready Applications".
Dodatkowo proste sprawy, takie jak miejsce przeznaczone na daną kontrolkę, są związane z językiem docelowym. Łańcuch znaków w języku angielskim może wymagać znacznie więcej przestrzeni po przetłumaczeniu na farsi. Znowu, wiele kontrolek wspiera właściwości zaprojektowane do pokonania tych problemów projektowych. Ustawienie właściwości AutoSize na kontrolce na wartość True automatycznie rozszerzy obszar kliencki kontrolki zgodnie z zawartym w niej tekstem.
Rola standardów UI
Aplikacje muszą także dążyć do zgodności ze wszystkimi istotnymi standardami związanymi z ich wyglądem i zachowaniem. Niektóre standardy są udokumentowane przez „właściciela" platformy. Przykładowo: Microsoft ma zbiór wyznaczników projektowania UI udokumentowany w MSDN. Książka Microsoft Windows User Experience opublikowana przez Microsoft Press jest zawarta w całości wewnątrz MSDN. Poruszając tematy takie jak projektowanie zorientowane na brak stron 630 i 631
TWORZENIE FORMULARZA
Typ projektu Windows Application
Projekt Windows Application składa się ze standardowej klasy formularza oraz w przypadku C# z domyślnej statycznej klasy Program. Po utworzeniu projektu natychmiast zaprezentowany zostanie czysty, standardowy formularz otwarty w edytorze formularzy.
Określanie formularza startowego
Chociaż domyślny projekt tworzy tylko jeden pojedynczy formularz, to można oczywiście w dowolnym czasie dodać wiele formularzy. Wywołuje to pytanie, w jaki sposób wskazać w czasie projektowania, który z nich ma być początkowo wyświetlany podczas uruchamiania (jeśli taki istnieje). Istnieją dwie metody:
Dla projektów Visual Basic początkowy formularz jest określany za pomocą okna dialogowego Project Properties. Lista rozwijana Startup Object w tym oknie dialogowym zawiera listę wszystkich prawidłowych obiektów formularzy. Po prostu wybiera się formularz, który chce się wyświetlić przy uruchomieniu, i wszystko jest już gotowe.
Przy projektach Visual C# potrzebne jest odrobinę bardziej złożone podejście. W zamyśle obiekt startowy C# to po prostu dowolna klasa, która implementuje metodę Main () .Wewnątrz ciała metody Main należy umieścić linię kodu, który osadza w instancji formularza metodę Application.Run, taką ja ta: Application.Run (new OrderForm()). Przypuszczając, że mamy klasę, która implementuje metodę Main, i kod, który wywołuje Application.Run w tej metodzie Main, możemy wybrać konkretny obiekt startowy z poziomu okna dialogowego Project Properties. Klasa Program utworzona w procesie budowania projektu zawiera już metodę Main i przy uruchamianiu wywołuje formularz domyślny Form1.
Dziedziczenie wyglądu innego formularza
Jeśli formularz ma wyglądać podobnie do innego, już utworzonego, to istnieje opcja wizualnego dziedziczenia tego wyglądu z innego formularza. Visual Studio udostępnia szablon elementu projektu Inherited Form w celu ułatwienia tej czynności.
Aby utworzyć formularz, który wizualnie dziedziczy z innego, należy wybrać Project/Add New Item. W oknie dialogowym Add New Item należy wybrać typ elementu Inherited Form. Okno dialogowe Inheritance Picker wymieni następnie wszystkie dostępne w bieżącym projekcie formularze, z których można dziedziczyć. Należy zauważyć, że istnieje także opcja ręcznego przeglądania istniejącego podzespołu, jeśli chce się dziedziczyć z formularza, który nie pojawił się na liście. Po wybraniu formularza bazowego Visual Studio utworzy nową klasę formularza. Ten kod będzie odzwierciedlał pochodzenie z klasy bazowej.
Właściwości i zdarzenia formularza
Formularz jest taki jak inne kontrolki: można używać okna Properties w IDE w celu kontrolowania różnych właściwości. Chociaż nie zajmiemy się tu nimi wszystkimi, to chcemy rozważyć parę kluczowych właściwości, które dotyczą procesu projektowania formularza.
Położenie początkowe
Właściwości StartPosition używa się do umieszczania okna formularza na ekranie podczas pierwszego wyświetlenia. Właściwość ta przyjmuje wartości typu wyliczeniowego FormStartPositon. Możliwe wartości są udokumentowane w tabeli 15.1.
Tabela 15.1. Wartości typu wyliczeniowego FormStartPosition
Wartość |
CenterParent |
CenterScreen |
Manuał |
WindowsDefaultBounds |
WindowsDefaultLocation |
Wygląd
Po wcześniejszym omówieniu priorytetów projektowania UI nie jest żadną niespodzianką, że wygląd formularza mocno wpływa na wrażenie użytkownika aplikacji. Zazwyczaj domyślne właściwości wyglądu są odpowiednie do wyświetlania typowych danych. Należy ustawić właściwości ForeColor i BackColor zgodnie z dowolnym schematem kolorów identyfikowanych dla aplikacji. Należy zauważyć, że podczas dodawania kontrolek do formularza większość z nich ma swoje własne wartości ForeColor określane tak, aby naśladowały kolor formularza.
Niektóre z właściwości pozwalają na implementację bardziej ekstrawaganckiego interfejsu użytkownika. Właściwość Opacity pozwala na implementację przezroczystości lub półprzejrzystości formularzy. Ta możliwość może być użyteczna w sytuacjach, gdy użytkownicy chcą zobaczyć część ekranu, który znajduje się pod oknem formularza. Poza właściwością Opacity można użyć właściwości Form.Backgroundlmage, aby ustawić obrazek jako tło formularza. Ta właściwość jest używana do wyświetlania subtelnych gradientów koloru lub grafik niemożliwych do osiągnięcia za pomocą właściwości BackColor.
Ze względu na cel, którym jest szybkie wykonanie formularza, większość czynności wykonywanych w widoku projektowym i opisanych w tym rozdziale składa się z określenia właściwości formularza i dodawania kontrolek z panelu Toolbox na formularz.
Zdarzenia formularza
Formularze dziedziczą tę samą sterowaną zdarzeniami architekturę, co inne kontrolki. Określone publiczne zdarzenia zdefiniowane w klasie Form są użyteczne jako punkty „wstrzykiwania kodu" w ciągłym życiu formularza.
Rysunek 15.3 pokazuje różne etapy (i odpowiadające im zdarzenia) od powstania do zamknięcia formularza. W celu reakcji na zdarzenie formularza najpierw trzeba wykonać procedurę obsługi zdarzeń.
Tworzenie procedury obsługi zdarzenia
Okno Properties programu Visual Studio udostępnia szybki mechanizm definiowania procedury obsługi zdarzenia. Najpierw należy wybrać interesujący formularz. Następnie kliknąć przycisk Events na pasku narzędzi okna Properties. W oknie ukaże się teraz lista wszystkich zdefiniowanych dla formularza zdarzeń. Klikając dwukrotnie zdarzenie, utworzy się pustą procedurę obsługi zdarzeń i otworzy ją w edytorze kodu. Procedura obsługi zdarzenia będzie miała prawidłową listę argumentów i będzie zgodna z ustalonymi konwencjami nazewnictwa procedur obsługi zdarzeń (typowo obiekt_nazwazdarzenia).
Rysunek 15.4 ukazuje zdarzenia formularza wewnątrz okna Properties.
Mając już formularz na miejscu, można zacząć umieszczać kontrolki na jego powierzchni.
Rysunek 15.4.
Zdarzenia formularza w oknie Properties
DODAWANIE KONTROLEK I KOMPONENTÓW
Podczas budowania bazującej na formularzach aplikacji projektowanie interfejsu użytkownika w rzeczywistości korzysta z trzech oddzielnych narzędzi w Visual Studio:
narzędzia Windows Forms Designer, udostępniającego powierzchnię formularza,
panelu Toolbox, który zawiera kontrolki do umieszczania na formularzu, oraz
przeglądarki właściwości, która jest używana do modyfikowania formularza i jego potomnych kontrolek, ich wyglądu i zachowania.
Ta trójka narzędzi IDE pozwala ma szybkie tworzenie formularzy w Visual Studio, szczególnie gdy związane jest to z tworzeniem zawartości formularza.
Termin kontrolka technicznie odnosi się do dowolnego obiektu .NET, który implementuje klasę Control. W praktyce używamy tego terminu do dowolnych wizualnych kontrolek zawartych na formularzu. Jest to przeciwieństwo komponentu, który ma wiele tych samych charakterystyk co kontrolka, ale nie eksponuje interfejsu wizualnego. Element Button jest przykładem kontrolki, element Timer jest przykładem komponentu.
Kontrolki i komponenty razem znajdują się w panelu Toolbox Dodawanie do formularza zarówno kontrolki, jak i komponentu jest tak łatwe, jak przeniesienie ich ikony z panelu Toolbox i umieszczenie na formularzu.
Po umieszczeniu kontrolki na formularzu edytor narysuje tę kontrolkę na formularzu, dając widok WYSIWYG wyglądu formularza w czasie wykonania. Komponenty są obsługiwane w odrobinę inny sposób. Edytor ma specjalny obszar nazywany paletą komponentów (ang. component tray). Dowolne komponenty umieszczane na formularzu są prezentowanie w tym miejscu. Pozwala to na interakcję z komponentem za pomocą myszy, podobnie jak z kontrolką, ale nie umieszcza jego reprezentacji graficznej na samym formularzu, ponieważ komponent nie ma umożliwiającego to aspektu wizualnego.
Rysunek 15.5 ukazuje obszar palety komponentów w edytorze formularzy.
Wskazówka:
Panel Toolbox można dostosowywać. Można dodawać i usuwać kontrolki z dowolnych jego zakładek. Należy w tym celu kliknąć prawym przyciskiem gdziekolwiek wewnątrz okna Toolbox i wybrać Choose Items. Uruchomi to okno dialogowe Choose Toolbox Items. Odtąd można wybierać lub usuwać kontrolki Toolbox. Jeśli kontrolka nie wyświetla zakładki.NET Framework Components lub COM Components, to w oknie dialogowym można przejść do podzespołu kontrolek i dodać go bezpośrednio.
Układ i pozycjonowanie kontrolek
Po położeniu kontrolek na formularzu edytor ma kilka funkcji przeznaczonych do automatyzowania typowych zadań związanych z ich układem, takich jak rozmieszczenie grupy kontrolek w pionie względem siebie. Ponownie odsyłamy do rozdziału 6., gdzie można znaleźć więcej informacji o narzędziach zwiększających produktywność. Jednak funkcje określania układu, chociaż wygodne z perspektywy projektowania, nie wpływają na zmiany położenia w czasie działania programu.
Jak poprzednio wspomniano, kontrolowanie zachowania w czasie wykonania wewnątrz formularza nadrzędnego jest ważne i wymaga uwagi, jeśli chce się zaimplementować formularz zgodnie z intencjami projektowymi. Oznacza to, że kontrolki nie tylko mają wyglądać zgodnie z projektem, ale także mają zachowywać się w określony sposób podczas zmiany rozmiarów formularza.
Najprostszym sposobem podkreślenia problemu związanego ze zmianą rozmiaru formularza jest zamieszczenie paru rysunków. Rysunek 15.6 pokazuje najprostszy formularz: etykietę, pole tekstowe i przyciski OK i Anuluj. Te kontrolki na formularzu zostały rozmieszczone dokładnie: z zachowaniem równych odstępów, ładnie wyrównane w pionie i poziomie. Jednym słowem, formularz ten wygląda tak, jak chciał tego programista.
Rysunek 15.6. Kontrolki ułożone na formularzu
Następnie użytkownik zaczął korzystać z tej aplikacji. Rysunek 15.7 ukazuje wyniki zmiany rozmiarów poziomych i pionowych formularza.
Ten wygląd nie jest oczywiście zgodny z zamierzeniami. Ładny, przejrzysty projekt formularza uległ zniszczeniu po zmianie jego rozmiarów. Prawdopodobnie użytkownik zmienił rozmiar formularza w celu uzyskania większej ilości miejsca w polu tekstowym lub umieścił okno aplikacji równolegle z innymi aplikacjami, powodując zmianę jego rozmiarów. Bez względu na powód jasne jest, że potrzebna jest dalsza interwencja programisty w celu utrzymania „prawidłowego" wyglądu bez względu na rozmiar formularza.
Rysunek 15.7. Efekt zmiany rozmiarów formularza
Po prostu oglądając rysunki przed i po, można zadecydować o strategii i odpowiedzieć sobie na pytanie „Co powinno się stać, gdy użytkownik zmieni rozmiar formularza?". Rysunek 15.8 przedstawia idealne rozwiązanie. Pole tekstowe „dotrzymało kroku" zmianie rozmiarów przez poziome rozszerzenie lub zmniejszenie szerokości. Przyciski poleceń zachowały swoje położenie względem siebie i pola tekstowego, ale nie zmieniły swoich rozmiarów. Ponadto etykieta pozostała w oryginalnym położeniu.
Rysunek 15.8. Reakcja na zmianę rozmiaru formularza
Każdy obiekt formularza ma swoje zdarzenie zmiany rozmiarów, które jest wywoływane zawsze, gdy zmienią się rozmiary obramowania formularza (zwykle jako wynik przesuwania ramki formularza w celu zwiększenia lub zmniejszenia jego rozmiarów). Ponieważ każda kontrolka ma właściwości pozycji takie jak Top, Left, Height i Width, można zaimplementować siłowe podejście w celu otrzymania formularza z rysunku 15.8. Pisząc wiele linii kodu dla każdej kontrolki, można ręcznie przesuwać lub zmieniać rozmiary kontrolek w odpowiedzi na zmianę rozmiaru formularza oraz pozycji innych kontrolek. Ale to podejście jest w najlepszym przypadku żmudne i daje w wyniku słaby kod, który musi być wykonywany za każdym razem podczas zmiany układu i położenia kontrolek.
Szczęśliwie edytor formularzy Visual Studio, w połączeniu z pewnymi standardowymi właściwościami kontrolek, przejmuje całą typową optymalizację zmiany rozmiarów podczas zmiany układu formularza. Przez kotwiczenie (ang. anchoring) i dokowanie (ang. docking) kontrolek można narzucać ich pozycję względem siebie oraz względem granic formularza.
Kotwiczenie
Kotwiczenie, jak sama nazwa wskazuje, jest koncepcją wymuszania lewej, górnej, prawej lub dolnej ramki w celu uzyskania statycznej, zakotwiczonej pozycji ramek na formularzu. Przykładowo, zakotwiczenie kontrolki etykiety do góry i lewej krawędzi formularza (jest tak domyślnie) spowoduje, że etykieta pozostanie w swojej dokładnej pozycji bez względu na sposób zmiany rozmiarów formularza. Każda właściwość Anchor może być określona przez kombinację wartości Top, Left, Bottom i Right. Przeglądarka właściwości kontrolek udostępnia wygodny edytor tej właściwości pokazany na rysunku 15.9. Wskazuje on graficznie strony kontrolki, które są zakotwiczone.
Rysunek 15.9. Ustawianie właściwości kotwiczenia
Kotwiczenie przeciwnych stron kontrolki daje interesujący efekt. Ponieważ każda strona musi zachować swoją pozycję względem stron formularza, sama kontrolka będzie się rozciągać w pionie lub poziomie, zależnie od ustawionych kotwic Top i Bottom lub Right i Left. Jest to dokładnie zachowanie, jakiego oczekiwaliśmy od pola tekstowego: chcieliśmy, aby jego wysokość i szerokość dostosowywały się podczas zmiany rozmiarów formularza. Kotwicząc wszystkie strony kontrolki, otrzymamy zachowanie pokazane na rysunku 15.8. Kontrolka automatycznie dostosowuje swoje rozmiary bez kodu wymaganego od programisty.
Kotwiczenie rozwiązuje także problem pozycjonowania przycisków poleceń. Jeśli zmieni się właściwość Anchor na Bottom, Right, to zostaną one zakotwiczone do dolnego prawego rogu
Uwaga
Domyślnie kontrolki są typowo zakotwiczone do górnej i lewej krawędzi. Co się jednak stanie, gdy nie podamy żadnych kotwic? W tym przypadku kontrolka utrzyma swoją dokładną pozycję, bez względu na działania zmiany rozmiarów. W efekcie osiągniemy to samo zachowanie co przy zakotwiczeniu do góry i na lewo, ponieważ formularze mają swoje własne lewe górne rogi podane jako „położenie".
formularza, co jest zgodne z ich zalecanym położeniem na formularzu. Ponieważ nie zakotwiczyliśmy pozostałych stron kontrolki, przyciski nie będą zmieniać rozmiarów. Porównajmy to z kotwiczeniem wykonanym dla pola tekstowego. Ponieważ zakotwiczyliśmy wszystkie strony, nie tylko zachowaliśmy jednolitą ramkę pomiędzy krawędzią pola tekstowego a formularza, ale także spowodowaliśmy rozciąganie pola tekstowego w obu kierunkach.
Dokowanie
W prostym formularzu pokazanym na rysunku 15.8 można zaimplementować większość logiki wyglądu za pomocą właściwości Anchor. Ale jeśli zwrócimy uwagę na ogólny plan ekranu CSR (rysunek 15.1), można zauważyć, że spełnienie niektórych wymagań może być trudne do wykonania za pomocą kotwic. Przykładowo, obszar wprowadzania danych powinien automatycznie rozszerzać się w pionie i poziomie, aby wypełnić dowolną przestrzeń pomiędzy listą zamówień, paskiem statusu i paskiem poleceń. Tutaj ratunkiem staje się koncepcja dokowania. Dokowanie jest używanie do przytwierdzania kontrolki do krawędzi sąsiednich kontrolek lub formularza, lub też używane do wymuszania wypełniania całej dostępnej przestrzeni niezajętej przez inne kontrolki.
Podobnie jak dla właściwości Anchor przeglądarka właściwości udostępnia graficzne narzędzie do ustawiania właściwości Dock (pokazane na rysunku 15.10).
Kontrolowanie automatycznego skalowania
Mechanizm formularzy Windows wspiera możliwość dynamicznej regulacji współrzędnych kontrolki w celu zachowania jej oryginalnych proporcji. Możliwość ta jest użyteczna, jeśli formularz lub kontrolka są wyświetlane w programie działającym w systemie o innych charakterystykach wyświetlania (rozdzielczości, DPI itp.) niż ten, na którym formularz lub kontrolka były zaprojektowane.
Prostym przykładem jest aplikacja używająca podczas projektowania stosownych 9-punktowych czcionek, która staje się prawie bezużyteczna, gdy jest wyświetlana w systemie z większym domyślnym rozmiarem czcionek. Ponieważ większość elementów UI automatycznie reguluje swoje wymiary na podstawie czcionki wyświetlanego na nich tekstu (takie jak paski tytułowe Windows oraz menu), może to wpłynąć na prawie każdy wizualny aspekt aplikacji formularza.
Kontrolki kontenerowe (na przykład dziedziczące po klasie ContainerControl, w tym typy Form i UserControl) od wersji .NET 2.0 obsługują dwie właściwości, które pozwalają na automatyczne rozwiązanie tych problemów bez większej interwencji programisty: AutoScaleMode oraz AutoScaleDimensions. AutoScaleMode określa wartość wyliczeniową wskazującą, jaki proces skalowania powinien być użyty oraz jego bazę (DPI lub rozdzielczość). Tabela 15.2 pokazuje możliwe wartości AutoScaleMode.
Tabela 15.2. Wartości wyliczeniowe AutoScaleMode
Dpi | Skalowanie względem rozdzielczości (96 DPI, 120 DPI i tak dalej). |
---|---|
Font | Skalowanie względem wymiarów używanej czcionki |
Inherit | Skalowanie związane z wartością AutoScaleMode klasy bazowej |
None | Brak automatycznego skalowania |
AutoScaleDimensions ustawia współrzędne (przez strukturę SizeF), dla których oryginalnie została zaprojektowana kontrolka. Powinno się to odnosić do rozmiaru czcionki lub DPI.
Rysunek 15.10. Ustawianie właściwości Dock
Używanie kontenerów
Kontenery to kontrolki .NET przeznaczone do przechowywania innych kontrolek. Można użyć kontenerów w połączeniu z właściwościami Anchor i Dock kontrolek w celu utworzenia skomplikowanego projektu. Chociaż istnieją różnorodne kontrolki kontenerów, najbardziej odpowiednie do kontroli układu są klasy FlowLayoutPanel, TableLayoutPanel oraz SplitContainer.
Obie klasy TableLayoutPanel i FlowLayoutPanel dziedziczą z bardziej ogólnej klasy Panel. Klasa Panel udostępnia bardzo wysokiego poziomu możliwości grupowania kontrolek. Jest to korzystne z perspektywy umieszczania, ponieważ można agregować grupę kontrolek w jedną grupę, umieszczając je na panelu. W ten sposób można działać na nich jako grupie. Przykładowo, wyłączając kontrolkę panelu, wyłączamy wszystkie umieszczone na nim kontrolki: TableLayoutPanel i FlowLayoutPanel nadbudowują tę funkcjonalność, udostępniając zdolność dynamicznego wpływania na pozycję umieszczanych na nich kontrolek.
TableLayoutPanel
Rozważmy serię etykiet i pól tekstowych służących do wprowadzania informacji adresowych. Standardowo są one umieszczane w tabelach zawierających kolumny i wiersze. TableLayoutPanel jest idealny dla implementacji tego zachowania, ponieważ automatycznie wymusza określenie kolumny i wiersza dla każdej kontrolki. Rysunek 15.11 pokazuje serię kontrolek etykiet i pól tekstowych zagnieżdżonych w panelu TableLayoutPanel. Należy zauważyć, że zmiana rozmiarów formularza (a przy tym panelu, który jest zadokowany tak, aby wypełniał całe wnętrze formularza) powoduje, że kontrolki panelu same regulują swoje położenie.
Rysunek 15.11.
Jeśli element w jednej z komórek wykracza poza jej granice, będzie automatycznie przesunięty w tej komórce. Udostępnia to te same możliwości układu, jakie HTML udostępnia dla interfejsów wyświetlanych w przeglądarkach.
Uwaga
Podczas dodawania komórki do panelu TableLayoutPanel dodawane jest do niej pięć właściwości: Cell, Column, Row, ColumnSpan i RowSpan. Te właściwości mogą być używane do zmiany położenia wiersza lub kolumny kontrolki wewnątrz panelu układu w czasie działania programu. Właściwości ColumnSpan i RowSpan są używane w ten sam sposób, jak ich odpowiedniki w świecie HTML. W .NET kontrolki, które wprowadzają do innych kontrolek nowe właściwości, są nazywane dostawcami rozszerzeń (ang. extender providers).
FlowLayoutPanel
FlowLayout Panel ma prostszy algorytm układu. Elementy są uporządkowane w pionie lub poziomie przez rozmieszczanie zbiorów kontrolek w kolejnych wierszach lub kolumnach zgodnie z potrzebami. Dwa ekrany pokazane na rysunku 15.12 ilustrują efekt zmiany rozmiarów panelu FlowLayoutPanel zawierającego zbiór kontrolek RadioButton.
Rysunek 15.12. FlowLayoutPanel
SplitContainer
Kontrolka SplitContainer jest rozbudowaną alternatywą dla oryginalnej kontrolki Splitter zawartej w .NET 1.0/l.l/Visual Studio 2003. Kontrolka ta reprezentuje połączenie dwóch paneli i linii rozdzielającej je w poziomie lub pionie. Linia ta pozwala użytkownikowi na ręczne dostosowanie przestrzeni, której każdy z paneli używa wewnątrz całego kontenera.
Rysunek 15.13 pokazuje wszechstronność tej kontrolki. Dwa elementy SplitContainer, jeden zagnieżdżony w panelu udostępnianym przez drugi, umożliwiają zmianę rozmiarów panelu na formularzu zarówno w pionie, jak i poziomie (panel 2 nie jest widoczny, ponieważ funkcjonuje jako kontener dla panelu SplitContainer z panelami 3 i 4). Przeciągając linię rozgałęźnika na prawo od panelu 1, można zwiększyć lub zmniejszyć poziomą przestrzeń zajmowaną na formularzu. To samo dotyczy linii podziału pomiędzy panelami 3 i 4. Przeciąganie jej wyreguluje współczynnik przestrzeni, która jest zajmowana przez oba panele w pionie.
Rysunek 15.13. Zmiana rozmiarów za pomocą SplitContainer. Poziomy SplitContainer zagnieżdżony w pionowym
ToolStripContainer
Większość aplikacji wspiera możliwość przeciągania i dokowania pasków narzędzi i menu do dowolnej strony formularza: góry, dołu, lewej lub prawej. Samo Visual Studio jest przykładem takiej aplikacji. Przeciągając pasek narzędzi Visual Studio, można zmienić jego położenie, przykładowo na lewą stronę formularza. Kontrolka ToolStripContainer pozwala na tę funkcjonalność także dla innych aplikacji. Jest ona kombinacją czterech paneli, z których każdy jest umieszczony na przeciwległych krawędziach formularza. Te panele są używane do przechowywanie kontrolek ToolStrip (więcej o nich za chwilę) oraz — w czasie wykonania — pozwalają użytkownikom na przenoszenie pasków narzędzi wewnątrz i pomiędzy tymi czterema panelami.
Uwaga:
Chociaż ToolStripContainer udostępnia wygodny sposób przytwierdzania pasków narzędzi do brzegów formularza, to nie istnieje niestety wbudowane wsparcie dla „pływających" pasków narzędzi.
Projektowanie jest proste — można przenosić kontrolki pomiędzy tymi czterema panelami w zależności od tego, gdzie chce się je umieścić na formularzu. Rysunek 15.14 ukazuje ToolStripContainer w trybie projektowania. Inteligentne znaczniki udostępniają kontrolę widoczności paneli górnego, lewego, prawego i dolnego. Każdy z nich jest domyślnie ukryty. Można kliknąć dowolną ze strzałek na brzegach kontenera w celu rozwinięcia odpowiedniego panelu i otrzymania miejsca do umieszczenia na nim pasków narzędzi.
Rysunek 15.14. ToolStripContainer w trybie projektowania
Poza wygodą umieszczania elementów wToolStripContainer wewnątrz widoku projektowego prawdziwą zaletą tej kontrolki jest automatyczne wsparcie dla przeciągania i upuszczania pomiędzy panelami w czasie działania. Oznacza to, że bez pisania linii kodu dotyczącego układu lub rozmieszczania mamy pełną funkcjonalność pozwalającą użytkownikom na umieszczanie ich menu lub pasków narzędzi, gdziekolwiek chcą wewnątrz formularza. Rysunek 15.15 pokazuje pasek narzędzi umieszczony w ToolStripContainer, który został przemieszczony z górnego na lewy panel w czasie pracy.
Rysunek 15.15. Pasek narzędzi przeniesiony wewnątrz ToolStripContainer
Wiele kontrolek ToolStrip może być także umieszczanych na dowolnym panelu kontenera ToolStripContainer. Rysunek 15.16 pokazuje kilka pasków poleceń umieszczonych na prawym panelu. Jak opisano dalej w tym rozdziale, współrzędna z kontrolki dyktuje jej miejsce na stosie.
Rysunek 15.16. Wiele pasków narzędzi umieszczonych na tym samym panelu
Istnieje jeszcze parę innych spraw związanych z układem i pozycjonowaniem formularza i kontrolek, ale podstawy zostały już opisane. Znając te koncepcje i posiadając ogólny projekt formularza, można zacząć korzystać z edytora.
Uwaga
Współdzielenie przestrzeni — poziome lub pionowe — wewnątrz kontenera ToolStripPanel jest czasem określane jako pływanie: kontrolki paska narzędzi mogą dowolnie przemieszczać się po panelu.
Wygląd i zachowanie kontrolek
Wygląd kontrolek jest określany przez zbiór podstawowych właściwości używanych do kontrolowania wyglądu formularza: elementy takie jak ForeColor, BackColor i Font określają wygląd większości kontrolek.
Style wizualne
Interesująca jest zdolność kontrolki do automatycznego zmieniania wyglądu w celu dostosowania się do aktualnie wybranej „kompozycji pulpitu", jeśli działa w systemie Windows . Zdolność ta jest włączana przez wywołanie metody Application.EnableVisualStyles. Rysunek 15.17 pokazuje formularz bez włączonych stylów wizualnych (po lewej) oraz z włączonymi stylami wizualnymi (po prawej).
Rysunek 15.17. Efekt Application.EnableVisualStyles
Kolejność przechodzenia
Domyślnie kolejność, w jakiej kontrolki na formularzu są wybierane jest taka sama jak ta, w jakiej zostały położone na formularzu. Aby jawnie określić kolejność przejścia dla wszystkich kontrolek formularza, IDE udostępnia tryb wyboru kolejności przejścia.
Aby wejść do trybu wyboru kolejności przejścia, należy wybrać z menu opcje View/Tab Order. Edytor formularzy zaopatrzy każdą z kontrolek w formularzu numerem. Liczba ta reprezentuje pozycję kontrolki w ogólnej kolejności przejścia przez formularz. Aby określić pożądaną kolejność przejścia, należy po prostu kolejno klikać na kontrolkach. Ich numery kolejności zmienią się automatycznie podczas klikania.
Wskazówki
Wskazówki to małe „chmurki", które wyświetlają tekst, gdy użytkownik przesuwa swój kursor nad kontrolką. Standardowo są one używane w celu udostępnienia pomocnych wskazówek lub opisów przeznaczenia kontrolki, jej działania itp. Elementy te są implementowane za pomocą klasy ToolTip i mogą być przypisane do kontrolek w czasie projektowania.
Klasa ToolTip jest przykładem dostawcy rozszerzeń (patrz poprzednia uwaga na temat dostawców rozszerzeń podczas rozważań na temat kontrolki TableLayoutPanel). Po dodaniu komponentu ToolTip do formularza każda kontrolka na formularzu będzie implementować właściwość ToolTip, która jest używana do przypisywania elementu ToolTip do określonej kontrolki.
Przykładowo, jeśli chce się dodać ToolTip do przycisku ToolStrip, to należy najpierw przeciągnąć komponent ToolTip nad formularz z panelu ToolBox. Następnie należy wybrać przycisk ToolStrip, do którego chce się dodać ToolTip, a następnie należy ustawić jego właściwość ToolTip tak, aby wskazywała na instancję ToolTip formularza.
Praca z kontrolkami ToolStrip
Większość standardowych, bazowych elementów wizualnych formularza może zostać zrealizowana za pomocą kontrolek ToolSt rip. Kontrolka ToolStrip działa jako kontener na inne kontrolki, które dziedziczą z ToolStripltem. Może ona zawierać różne typy kontrolek: przyciski, pola wyboru, etykiety, separatory, pola tekstowe, a nawet paski postępu. Klasa ToolStrip jako taka jest używana do bezpośredniej implementacji pasków narzędzi na formularzu, a także funkcjonuje jako klasa bazowa dla kontrolek StatusStrip i MenuStrip.
Kontrolki ToolStrip dostarczane są z pokaźną listą wbudowanych możliwości. Wewnętrznie wspierają one na przykład przeciąganie elementu z jednego paska narzędzi do innego, dynamiczną zmianę kolejności i obcinanie elementów paska narzędzi, gdy użytkownik zmieni rozmiar paska lub formularza, i w pełni wspierają różne kompozycje systemu operacyjnego i schematy wyświetlania.
Różne odmiany kontrolki ToolStrip mają pewne wspólne cechy:
W czasie projektowania inteligentne znaczniki umożliwiają szybki i łatwy dostęp do częstych poleceń.
Wspierana jest wewnętrzna edycja kontrolek potomnych (na przykład oferowany jest interfejs dodawania, usuwania i zmieniania elementów wewnątrz ToolStrip, StatusStip oraz MenuStrip za pomocą myszy).
Okno dialogowe Items Collection Editor pozwala na uzyskanie lepszej kontroli nad właściwościami kontrolek-dzieci, a także pozwala na ich dodawanie, zmianę kolejności i usuwanie.
Paski narzędzi wspierają modułowy model wizualizacji. Można zmienić wizualny generator paska narzędzi na gotowy obiekt generowania lub własny obiekt, tak aby osiągnąć bezwzględną kontrolę nad wyglądem paska narzędzi.
Na podstawie wyjściowego projektu formularza można się domyślić, że potrzebne będą menu, paski narzędzi i paski stanu, dlatego kontrolka ToolStrip i kontrolki pochodne od niej będą pełnić kluczową funkcję.
Tworzenie menu
Kontrolki MenuStrip pozwalają na wizualną konstrukcję głównego menu formularza. Przeciąganie i upuszczanie tej kontrolki z panelu Toolbox na pusty formularz automatycznie dokuje pasek menu na górze formularza (rysunek 15.18).
Rysunek 15.18. Menu umieszczone na formularzu
Po umieszczeniu kontrolki MenuStrip na formularzu wybranie jej aktywuje znacznik inteligentny (znaczniki inteligentne zostały opisane w rozdziale 8., „Korzystanie z narzędzi zwiększających produktywność"). Klikając znacznik inteligentny, można szybko wykonać następujące czynności:
automatycznie wprowadzić standardowe elementy do menu,
zmienić właściwości menu RenderMode, Dock oraz GripStyle,
edytować elementy menu.
Korzystanie ze zdolności automatycznego wyposażenia paska menu w standardowy zbiór menu zaoszczędza parę minut czasu projektowania w porównaniu z ręcznym podejściem. Rysunek 15.19 pokazuje wynik.
Rysunek 15.19. Menu z elementami standardowym
Wstawione zostały nie tylko standardowe elementy nadrzędnego menu, czyli File, Edit, Tools i Help, ale także elementy podmenu dla każdego z nich. Tabela 15.3 wskazuje dokładną strukturę, która jest wynikiem skorzystania z funkcji Insert Standard Items.
Aby umieścić dodatkowe elementy na pasku menu, można użyć bloku wewnątrz menu z etykietą Type Here. Za każdym razem, gdy wpisze się w tym bloku nazwę polecenia, pojawią się dodatkowe pola, a element zostanie dodany do paska menu (rysunek 15.20).
Tworzenie paska narzędzi
Następnym elementem, który ma być umieszczony na formularzu, jest pasek narzędzi. Paski narzędzi w .NET 2.0 i nowszych wersjach platformy są implementowane bezpośrednio za pomocą kontrolek Tool Strip. Jak wspomniano wcześniej, kontrolki ToolStrip mogą zawierać wiele kontrolek-dzieci. Każda z nich dziedziczy z klasy bazowej ToolStripltem. Rysunek 15.21 pokazuje kontrolki-dzieci, które mają być zaimplementowanie wewnątrz paska narzędzi.
W rzeczywistości interaktywne funkcje układu dla paska narzędzi działają w taki sam sposób, jak dla paska menu. Przeciąganie kontrolki na formularz daje w wyniku pustą kontrolkę ToolStrip
Tabela 15.3. Standardowe elementy menu
zadokowaną na górze formularza pod istniejącą kontrolką menu. Można szybko dodać listę standardowych elementów, korzystając z technologii inteligentnych znaczników i wybierając Insert Standard Items.
Rysunek 15.22 przedstawia działający formularz z dodaną kontrolką ToolStrip.
Jeśli chce się pozwolić użytkownikom na przenoszenie paska narzędzi lub menu pomiędzy czterema krawędziami formularza, trzeba użyć ToolStripContainer. W rzeczywistości istnieje tutaj pewien skrót: można wziąć dowolną z kontrolek ToolSt rip znajdujących się aktualnie na formularzu i dodać ją do ToolSt ripContainer za pomocą kilku kliknięć myszą. Jednym z elementów dostępnych z poziomu znaczników inteligentnych paska narzędzi jest komenda Embed in a ToolStripContainer. Jeśli wykona się to polecenie na pasku narzędzi dodanym już do przykładowego formularza, Visual Studio wykona dwie rzeczy: doda ToolStripContainer do formularza i umieści na nim wybrany ToolStrip, lokując go w górnym panelu kontenera.
Rysunek 15.20. Ręczne dodawanie elementów menu
Rysunek 15.21.Klasy dziedziczące z ToolStripItem
Tworzenie paska statusu
Paski statusu udostępniają użytkownikom informację zwrotną na temat bieżącego statusu aplikacji, postępu działania, szczegółów w kontekście obiektu zaznaczonego na formularzu itp. Kontrolka StatusStrip udostępnia tę funkcjonalność w .NET 2.0 — Visual Studio 2005 i zastępuje kontrolkę StatusBar znajdującą się w poprzednich wersjach.
Podobnie jak inne elementy pochodzące odToolStrip kontrolka StatusStip funkcjonuje jako kontener. Jego zdolność do zawierania etykiet w dodatku do pasków postępu, list rozwijanych oraz przycisków typu SplitButton czyni go znacznie potężniejszą kontrolką niż StatusBar.
Rysunek 15.22. Główny formularz z kompletnym menu i paskami narzędzi
Uwaga
Do określania „głębokości" kontrolek na formularzu używa się współrzędnej z. Jeśli dwie kontrolki znajdują się w tym samym miejscu formularza, to poszczególne współrzędne kontrolek wskazują, która z nich jest na wierzchu, a która pod spodem. Warstwy te można kontrolować wewnątrz IDE, jeśli kliknie się kontrolkę prawym przyciskiem myszy i użyje poleceń menu Send To Back oraz Bring To Front.
Współrzędna z odgrywa ważną rolę w umieszczaniu zadokowa- nych kontrolek. Są one umieszczane w tabeli w narastającej kolejności ich indeksów na formularzu. Przykładowo, jeśli wybierze się ToolSt rip i wywoła komendę Send To Back, to kolejność kontenerów MenuSt rip i ToolStrip zostanie zmieniona. Najpierw umieszczony zostanie kontener ToolStrip (w górnej części formularza), a później MenuSt rip (tuż pod elementem ToolStrip).
Rysunek 15.23 pokazuje fikcyjny formularz Contoso CSR z StatusStrip zadokowanym na dole formularza. W trybie projektowania można zobaczyć przyciski rozwijane, które zawierają zaznaczenie dla każdej z czterech obsługiwanych kontrolek-dzieci. W celu demonstracji tego
Rysunek 15.23. StatusStrip w trybie projektowania
prototypu należy dodać etykietę do raportowania ogólnego statusu aplikacji i dodatkowo etykietę i pasek postępu do wykorzystania podczas długotrwałych operacji odczytu danych lub edycji.
Domyślnie kontrolki-dzieci będą dodawane według wzorca układu pływającego od lewej do prawej wewnątrz szablonu StatusSt rip. Za pomocą zaledwie sześciu kliknięć (po dwa na element) można dodać te kontrolki do paska. Możliwości edycji w miejscu są wspaniałe i umożliwiają szybkie określenie wyglądu i zachowania paska. W celu większej kontroli nad kontrolkami-dziećmi można użyć okna dialogowego Items Collection Editor.
Wskazówka
Klikając dowolną z kontrolek-dzieci StatusStrip i wybierając ConrertToy można szybko zmienić typ kontrolki. Przykładowo, jeśli ma się etykietę na pasku, a chce się mieć przycisk rozwijany, klika się etykietę prawym przyciskiem i wybiera ConrertTo Drop- DownButton. Zaoszczędza to wysiłku związanego z usuwaniem kontrolki i dodawaniem nowej.
Edytowanie elementów StatusStrip
Należy używać inteligentnych znaczników StatusSt rip oraz wybierać Edit Items w celu uruchomienia okna dialogowego Item Collection Editor. Edytor ten daje bezpośredni dostęp do właściwości wszystkich zawartych w nim kontrolek i pozwala na edycję, usuwanie i zmianę kolejności elementów wewnątrz paska statusu (rysunek 15.24).
Rysunek 15.24. Items Collection Editor
Korzystając z kilku właściwości, można poprawić układ i wygląd swoich elementów. Rysunek 15.25 ukazuje domyślny układ dodawanych kontrolek. Chcemy, aby pasek postępu i jego etykieta znajdowały się z prawej strony paska statusu, a etykieta statusu po jego lewej stronie, zajmując całą pozostałą przestrzeń.
Rysunek 15.25. Domyślne elementy StatusStrip
Aby tego dokonać, trzeba ustawić właściwość Spring na True dla etykiety umieszczonej najbliżej lewej krawędzi. Spowoduje to powiększenie etykiety i wypełnienie przez nią całej dostępnej powierzchni paska statusu. Następnie ustawiamy jej właściwość TextAlignment, aby umieścić tekst na lewo od regionu etykiety i zmienić właściwość Text na coś bardziej odpowiedniego.
Rysunek 15.26 ukazuje owoce naszej pracy.
Rysunek 15.26. Końcowy wygląd StatusStrip
Wyświetlanie danych
Do tej pory zaledwie dotknęliśmy elementów formularza, które udostępniają podstawową nawigację dla użytkownika, status, polecenia itd. Jednak dopiero możliwości dostępu, wyświetlania i edycji danych (relacyjnych lub nie) stanowią rzeczywistą wartość aplikacji takiej jak fikcyjna Contoso CSR. Szczegółami pracy z bazami danych zajmiemy się w następnym rozdziale. Tutaj opiszemy niektóre podstawowe kontrolki służące do wyświetlania danych na formularzu.
Dane hierarchiczne
Kontrolka TreeView jest idealna do prezentacji danych hierarchicznych i dlatego wygodnie można w niej zamieszczać listy uporządkowanych rekordów (które mogą być grupowane wg różnych kryteriów). Po pierwsze, dodajmy kontrolkę SplitContainer. Będzie ona dzielić lewą wewnętrzną przestrzeń formularza na dwa osobne panele. Jeszcze jeden panel będzie zawierał funkcję przeszukiwania zamówień. Będzie on zadokowany do góry lewego podzielonego panelu. TreeView będzie wypełniać pozostałą część lewego panelu, a prawy panel będzie zawierał pola danych (pola tekstowe, etykiety, pola wyboru itd.) dla poszczególnych rekordów CSR.
Kontrolki TreeView prezentują dane jako listę węzłów. Każdy węzeł może służyć jako rodzic dla dodatkowych węzłów. Typowo dla aplikacji obsługujących bazę danych zawartość TreeView tworzy się, łącząc TreeView z bazą danych lub programowo przechodząc przez zbiór wyników i dodając do listy węzłów TreeView za pomocą jego API. Ponadto można kontrolować zawartość TreeView w widoku projektowym, uruchamiając TreeNode Editor.
TreeNode Editor
TreeNode Editor (rysunek 15.27) to okno dialogowe, które działa podobnie jak Items Collection Editor opisany wcześniej. Pozwala na dodawanie, edycję i usuwanie elementów z kontrolki TreeView. Okno dialogowe edytora uruchamia się, wybierając Edit Nodes ze znaczników inteligentnych TreeView.
Rysunek 15.27. Korzystanie z edytora węzłów
Korzystając z przycisków Add Root i Add Child, można wstawiać nowe węzły do struktury danych drzewa na dowolnym poziomie zagnieżdżenia. Rysunek 15.27 pokazuje ręcznie wstawione węzły z danymi testowymi, aby można było zobaczyć, jak będzie wyglądać lista zamówień, gdy węzłem- -rodzicem jest firma, a instancje zamówień występują jako jej węzły-dzieci. Każdy element lubwęzeł w TreeView składa się z dwóch części — obrazu i tekstu. Obraz jest opcjonalny. Aby uzyskać zdolność przyłączenia ikony do węzła, należy zacząć od przypisania kontrolki ImageList do kontrolki TreeView.
Korzystanie z ImageList
Kontrolki ImageList funkcjonują jako dostawcy obrazów dla innych kontrolek. Utrzymują one kolekcje obiektów obrazów, które są oznaczane przez kolejną pozycję lub klucz. Kontrolka, która udostępnia właściwość ImageList, może odnosić się do komponentu ImageList i używać jego obrazów. Przykładami kontrolek, które mogą korzystać z komponentu ImageList, są ListView, ToolSt rip oraz TreeView.
Uwaga
Visuał Studio 2008 jest dostarczane z olbrzymią biblioteką obrazów, które mogą być używane z TreeView lub dowolną inną kontrolką wymagającą standardowych typów grafik, jak paski narzędzi i menu. Domyślnie pliki obrazów są umieszczane w C:\Program Files\Microsoft Visual Studio 9.0\Common7\VS2008ImageLibrary.
ImageList nie ma wizualnej reprezentacji na formularzu. Innymi słowy, nie można zobaczyć samego elementu ImageList. Jego jedynym zadaniem jest bycie komponentem na zapleczu dostarczającym obrazy dla innych kontrolek. Przeciągnięcie ImageList do widoku projektowego będzie umieszczać instancję tego komponentu w zasobniku komponentów (rysunek 15.28). Można następnie używać okna dialogowego Images Collection Editor do dodawania, edycji i usuwania obrazów zawartych w komponencie. Zmienianie obrazów związane z listą obrazów automatycznie zmienia obrazy użyte przez kontrolki, do których się odnosi ImageList.
Rysunek 15.29 ukazuje kilka obrazów dodanych do wykorzystania w kontrolce TreeView. Aby włączyć TreeView do korzystania z tych obrazów, należy wykonać dwie czynności:
Przypisać właściwość TreeView. ImageList, aby wskazywała na instancję komponentu ImageList (w tym przypadku ImageListl).
Określić obraz powiązany z węzłem za pomocą kodu lub okna dialogowego TreeNode.
Z komponentem ImageList na miejscu i TreeView umieszczonym na lewym panelu SplitContainer formularz jest prawie ukończony z perspektywy projektowania. Pozostało tylko umieścić serię pól, które będą wyświetlać dane dla rekordów wybranych w kontrolce TreeView.
Można dodać te elementy, po prostu przeciągając grupę pól tekstowych i etykiet nad TableLayoutPanel, a następnie dokując całość w otworzonym panelu SplitContainer. Ponieważ jednak w rzeczywistości chcemy traktować to jako spójną jednostkę w celu ułatwienia pozycjonowania, możliwego wiązania danych itp., zamiast tego utworzymy kontrolkę użytkownika do wyświetlania rekordów CSR.
Rysunek 15.28. ImageList dodane do widoku projektu formularza
Dane tabelaryczne
Kontrolka DataGridView jest premiowaną kontrolką Visual Studio 2008 służącą do wyświetlania danych w formacie tabelarycznym. Udostępnia format wierszy i kolumn do wyświetlania danych z różnorodnych źródeł. Rysunek 15.30 ukazuje DataGridView z otwartym menu znaczników inteligentnych, które umożliwia szybki dostęp do właściwości kolumn kontrolki tabeli, a także pozwala na bezpośrednie połączenie DataGridView ze źródłami danych.
Rysunek 15.30. Kontrolka DataGridView
Źródła danych
Kontrolka DataGridView obsługuje różnorodne źródła danych. Przykładowo, wspierane są scenariusze wyświetlania par nazwa-wartość z kolekcji oraz strumienia danych ze zbiorów z relacyjnych baz danych. Jeśli wybierze się źródło danych dla zestawu, to kolumna zostanie dodana do tabeli dla każdej kolumny, która pojawia się w źródle danych, a dane wiersza będą automatycznie dostarczane wewnątrz kontrolki DataGridView.
Dane mogą być wyświetlane w kontrolce tabeli wizualnej także w „nieograniczonym" trybie. Korzystając z API wiersza lub kolumny, można programowalnie zdefiniować strukturę tabeli i dodawać dane w czasie działania programu.
Typy komórek
Każda poszczególna komórka w DataGridView funkcjonuje tak, jakby była zagnieżdżoną kontrolką. Każda komórka może przedstawiać podlegające jej dane na różne sposoby. Wszystkie pola wyboru, listy rozwijane, łącza, przyciski oraz pola tekstowe są obsługiwanymi typami komórek. Poza możliwością wizualizacji danych każda komórka ma także swój własny zbiór zdarzeń, które mogą być obsłużone w kodzie. Przykładowo, można obsłużyć zdarzenia umieszczenia wskaźnika myszy nad daną komórką lub usunięcia go znad niej.
Więcej na ten temat w rozdziale 18., „Praca z bazami danych".
TWORZENIE WŁASNYCH KONTROLEK
Jeśli żadna z zestawu kontrolek .NET nie spełnia konkretnych wymagań, to można utworzyć swoje własne kontrolki do użycia w formularzu Windows. Istnieją na to trzy sposoby:
Można utworzyć klasą potomną istniejącej kontrolki i zmodyfikować lub rozszerzyć jej zachowanie i wygląd.
Można utworzyć kontrolkę użytkownika (ang. user control), składając razem kilka kontrolek.
Można utworzyć własną kontrolkę (ang. custom control), od podstaw implementując jej wygląd i zachowanie.
Dziedziczenie z istniejącej kontrolki
Dziedziczenie z istniejącej kontrolki jest najlepszym sposobem, jeśli potrzebna jest tylko niewielka modyfikacja standardowej kontrolki .NET Framework. Dziedzicząc z istniejącej klasy kontrolki, korzystamy z jej zachowania i wyglądu. Do programisty należy dodanie specjalistycznego kodu do nowej klasy kontrolki.
Załóżmy, że chcemy otrzymać pole tekstowe, które będzie zmieniać kolor na czerwony za każdym razem, gdy wprowadzone zostaną dane liczbowe (czyli inne niż litery). Można to łatwo osiągnąć za pomocą zaledwie dwóch linii kodu umieszczonych w zdarzeniu TextChanged kontrolki TextBox, lecz implementacja tego zachowania we własnej klasie umożliwi ponowne jego wykorzystanie.
Rozpoczynamy od dodania do projektu nowej kontrolki użytkownika. Standardowo kontrolki użytkownika dziedziczą z klasy UserControl. Ponieważ chcemy dziedziczyć z klasy TextBox, powinniśmy zmienić definicję klasy, korzystając z edytora kodu. Następnie możemy umieścić nowy komponent na formularzu i korzystać z jego funkcji.
Praca z odziedziczoną kontrolką
Ponieważ TextBox ma UI, nie jest potrzebna żadna praca związana z wyglądem odziedziczonej kontrolki. W rzeczywistości działa ona tak, jak każda inna kontrolka pola tekstowego w edytorze formularzy (rysunek 15.31).
Rysunek 15.31. Odziedziczona kontrolka na formularzu
Okno Properties dla kontrolki zachowuje się zgodnie z oczekiwaniami, a dwukrotne kliknięcie kontrolki przenosi bezpośrednio do otwartego okna edytora kodu. W skrócie: odziedziczona kontrolka pozwala na projektowanie formularza bez zmian w stosunku do oryginalnej i nie wymaga dodatkowego wysiłku programisty.
Definiowanie kontrolki użytkownika
Kontrolka użytkownika jest pod względem technicznym taka sama, jak inne klasy tworzone przez programistę. Posiada ona reprezentację graficzną i dlatego Visual Studio udostępnia dla niej taki widok projektu, jak dla formularzy Windows, pozwalający na budowanie kontrolki metodą przeciągnij i upuść.
Kontrolki użytkownika są kontrolkami złożonymi. Oznacza to, że są konstruowane z jednej lub wielu istniejących kontrolek .NET. Tak jak w przypadku kontrolki odziedziczonej interfejs użytkownika jest dziedziczony z natywnych kontrolek składowych, co sprawia, że budowanie kontrolek i ich używanie w widoku projektu jest łatwe.
Istnieją dwa podejścia do procesu tworzenia kontrolki użytkownika — można utworzyć oddzielny projekt Windows Control Library lub po prostu dodać klasę kontrolki użytkownika do istniejącego projektu Windows Forms.
Tworzenie oddzielnego projektu pozwala na umieszczenie kontrolki użytkownika w oddzielnym zestawie. Wtedy można traktować kontrolkę użytkownika jako czarną skrzynkę, co daje większą elastyczność z perspektywy kontrolowania źródła i pozwala na współdzielenie tej kontrolki w wielu projektach. W aplikacjach produkcyjnych jest to najlepszy sposób. Jednak dla prostych prototypów, takich jak wykonana tu aplikacja CSR, łatwość i prostota dodawania tylko nowej klasy do istniejącego projektu czyni to podejście preferowanym. Klasa ta powinna znajdować się także wewnątrz tej samej przestrzeni nazw co klasa formularza.
W przypadku przechodzenia z prototypowania do rzeczywistego programowania produkcyjnego nic nie stoi na przeszkodzie, aby przenieść tę kontrolkę przez proste skopiowanie pliku klasy i umieszczenie go w oddzielnym projekcie biblioteki kontrolek.
Po dodaniu klasy kontrolek użytkownika do projektu ukaże się edytor kontrolek użytkownika (rysunek 15.32). Ten widok projektowy działa dokładnie w ten sam sposób jak edytor formularzy. Aby zbudować kontrolkę użytkownika, należy przenosić komponenty lub kontrolki z Toolbox na powierzchnię edytora.
Rysunek 15.32. Edytor kontrolek użytkownika
Dodawanie kontrolek
Oczywiście elementy, których używa się do budowania złożonej kontrolki, całkowicie zależą od planowanej funkcjonalności. Przykładowo, aby utworzyć kontrolkę planowania zamówień, powinno się myśleć na temat podlegającej struktury danych zamówienia. Rekord zamówienia może się składać z:
numeru zamówienia,
serii dat, przykładowo wystawienia zamówienia, dostawy itp.,
listy elementów zawartych w zamówieniu,
informacji koniecznych do wystawienia rachunku i adresu dostawy,
komentarzy.
Ponieważ na jednym ekranie ma zmieścić się wiele informacji, warto tu skorzystać z TabControl. Jest to jeszcze jeden kontener ogólnego przeznaczenia, który pozwala na organizację zawartości na wielu stronach, które są dostępne za pomocą zakładek. Na każdej z zakładek można umieścić TableLayout Panel i zaimplementować większość pól zamówienia jako proste etykiety i pola tekstowe.
Cały proces składania tych kontrolek w jedną kontrolkę użytkownika działa identycznie jak w edytorze formularzy. Można przeciągać i upuszczać kontrolki z Toolbox na powierzchnię edytora kontrolek użytkownika. Rysunek 15.33 pokazuje kontrolkę użytkownika OrderDisplay z kompletnym interfejsem użytkownika
Rysunek 15.33. Projektowanie kontrolki użytkownika
Zagnieżdżanie kontrolek użytkownika
Teraz, gdy ukończyliśmy tworzenie kontrolki użytkownika, pozostało tylko zagnieździć ją na podstawowym formularzu. Jeśli skompiluje się projekt, Visual Studio automatycznie rozpozna klasę kontrolki użytkownika i zamieści dla niej wpis w panelu Toolbox. Dzięki temu można będzie po prostu za pomocą myszy przeciągnąć i upuścić kontrolkę OrderDisplay w celu jej zaimplementowania.
Na rysunku 15.34 można zobaczyć element OrderDisplay z panelu Toolbox i rezultaty przeciągnięcia go na powierzchnię formularza.
Rysunek 15.34. Kontrolka użytkownika w panelu Toolbox i na formularzu
Tworzenie własnej kontrolki
Własne kontrolki reprezentują najwyższy stopień złożoności, ponieważ są tworzone od podstaw. Z tego powodu są trudne do zaprogramowania, ponieważ wymagają nie tylko troski o funkcjonalność, ale także o każdy pojedynczy aspekt wizualny. Ponieważ fizyczny interfejs użytkownika własnej kontrolki musi być napisany w 100% za pomocą własnego kodu, nauka tworzenia takich kontrolek jest bardzo trudna.
Ponieważ większość pracy związanej z tworzeniem własnych kontrolek odbywa się na poziomie kodu, nie będziemy podejmować próby szczegółowego opisu tego tematu. Jednak powinno się zwrócić uwagę, że proces ten zaczyna się w taki sam sposób, jak dla innych rodzajów kontrolek: Visual Studio ma szablon projektu własnej kontrolki. Dodanie go do swojego projektu generuje podstawowy kod, a reszta należy do programisty.
Uwaga
Kod rysujący interfejs użytkownika kontrolki umieszcza się w procedurze obsługi zdarzenia OnPaint. Chociaż tak zwane kontrolki „rysowane przez programistę" mogą zawierać złożony kod rysowania, to na szczęście edytor formularzy skorzysta z dowolnego kodu umieszczonego w zdarzeniu OnPaint do wyrysowania kontrolki w czasie projektowania. Oznacza to, że nadal można używać trybu WYSIWYG nawet dla własnych kontrolek.
PODSUMOWANIE
W tym rozdziale opisaliśmy różnorodne możliwości projektowania edytora Windows Forms Designer. Formularze Windows są potężną technologią warstwy prezentacji, a Visual Studio 2008 udostępnia zestaw narzędzi do szybkiego budowania efektownych, bogatych interfejsów użytkownika bazujących na tej technologii.
Rola edytora formularzy, panelu Toolbox oraz okna Properties została opisana w kontekście dostarczania nowoczesnych, dobrze przemyślnych, zgodnych ze standardami interfejsów użytkownika dla większości aplikacji Windows .NET. Opisane tu narzędzia znacznie ułatwiają proces projektowania i tworzenia formularzy.