System zdarzeń - wyzwalanie i nasłuchiwanie

Podobne dokumenty
MVVM Light Toolkit. Julita Borkowska

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Programowanie obiektowe

Politechnika Poznańska Wydział Budowy Maszyn i Zarządzania

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Dodanie nowej formy do projektu polega na:

Rozwój aplikacji modułowych Paweł Brudnicki. Dodanie modułu

Programowanie obiektowe

Laboratorium programowania urządzeń mobilnych

Rys. 3. Kod elementów na stronie po dodaniu kontrolek podstawowych.

Temat: Programowanie zdarzeniowe. Zdarzenia: delegacje, wykorzystywanie zdarze. Elementy Windows Application (WPF Windows Presentation Foundation).

Programowanie zaawansowane

Programowanie obiektowe

Wprowadzenie do programowania

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

Instrukcja laboratoryjna cz.3

Aplikacje w środowisku Java

xmlns:prism= c. <ContentControl prism:regionmanager.regionname="mainregion" />

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Przykładowa dostępna aplikacja w Visual Studio - krok po kroku

Przewodnik krok po kroku:

Aplikacje Internetowe

Logger. Następnie w klasie Bootstrapper muimy zarejestrować nasz nowy logger:

Soneta Sp. z o.o. Standardowe kreatory CRM

Wzorce projektowe. dr inż. Marcin Pietroo

TEMAT : KLASY DZIEDZICZENIE

Kurs programowania 2 - listy

Wykład 8: klasy cz. 4

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

Budowa aplikacji z graficznym interfejsem użytkownika - GUI (Graphic User Interface)

Tworzenie oraz zarządzanie użytkownikami w AD -Win Serwer 2008

Programowanie obiektowe

Podstawy Programowania 2

Graphic User Interfaces pakiet Swing

Instrukcja laboratoryjna nr.4

Wprowadzenie do projektu QualitySpy

Multimedia JAVA. Historia

Systemy wirtualnej rzeczywistości. Komponenty i serwisy

using System;... using System.Threading;

Klasy abstrakcyjne i interfejsy

Programowanie obiektowe

Wprowadzenie do środowiska Visual Studio cz. 2 (ćwiczenie wykonywane zdalnie) Wykorzystanie Wirtualnego portu COM

Programowanie obiektowe

Specyfikacja projektów zaliczeniowych

Komponenty wizualne i XAML

Projekt Hurtownia, realizacja rejestracji dostaw produktów

Programowanie obiektowe, wykład nr 6. Klasy i obiekty

Delphi podstawy programowania. Środowisko Delphi

Szybki Start. Informacje o module

10. Programowanie obiektowe w PHP5

Java Podstawy. Michał Bereta

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Diagram klas UML jest statycznym diagramem, przedstawiającym strukturę aplikacji bądź systemu w paradygmacie programowania obiektowego.

Programowanie obiektowe

1 LINQ. Zaawansowane programowanie internetowe Instrukcja nr 1

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami.

MVVM Light Toolkit Przewodnik krok po kroku

PHP 5 język obiektowy

Programowanie obiektowe

Wzorce projektowe. dr inż. Marcin Pietroo

Wykład 5 Okna MDI i SDI, dziedziczenie

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04

Laboratorium Systemów Operacyjnych

Projekt Hurtownia, realizacja rejestracji dostaw produktów

Dziedziczenie. Tomasz Borzyszkowski

OBIEKTY PHP. G. Panuś

Singleton. Cel: Przykład: Zastosowanie: Zapewnienie, że klasa ma tylko jedną instancję i dostarczenie globalnego dostępu do niej.

oprogramowanie mobilne Instrukcja obsługi PSR 2010

Numerowanie obiektów (wzorów, rysunków, tabel, literatury)

Programowanie obiektowe

Ćwiczenie 8. Kontrolki serwerowe

Kompilacja javac prog.java powoduje wyprodukowanie kilku plików o rozszerzeniu.class, m.in. Main.class wykonanie: java Main

Twoja ulotka instrukcja obsługi programu

Klasy i obiekty cz II

MVVM i XAML w Visual Studio 2015 / Jacek Matulewski. Gliwice, cop Spis treści

Aplikacja (oprogramowanie) będzie umożliwiać przygotowanie, przeprowadzenie badania oraz analizę wyników według określonej metody.

Zdarzenia i polecenia

Informatyka II. Laboratorium Aplikacja okienkowa

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

KONFIGURACJA SERWERA USŁUG INTERNETOWYCH WWW ORAZ FTP

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

Programowanie obiektowe

A Zasady współpracy. Ocena rozwiązań punktów punktów punktów punktów punktów

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Wstęp. Ale po co? Implementacja

Microsoft.NET: ASP.NET MVC + Entity Framework (Code First)

Tworzenie prezentacji w MS PowerPoint

Programowanie obiektowe

D:\DYDAKTYKA\ZAI_BIS\_Ćwiczenia_wzorce\04\04_poprawiony.doc 2009-lis-23, 17:44

Język JAVA podstawy. Wykład 4, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Aplikacje w środowisku Java

INSTRUKCJA INSTALACJI APLIKACJI PROF- EAN 2

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Materiały do zajęć VII

Typy, klasy typów, składnie w funkcji

Zaawansowane programowanie w C++ (PCP)

Zaawansowane aplikacje internetowe - laboratorium

Java: otwórz okienko. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Platformy Programistyczne Podstawy języka Java

Transkrypt:

System zdarzeń - wyzwalanie i nasłuchiwanie Informacje o module Opis modułu W tym rozdziale dowiesz się czym są zdarzenia silverlight, jakie rodzaje zdarzeo obsługuje oraz jakie strategie informowania o zajściu zdarzenia wykorzystano tworząc strukturę komponentów wizualnych. Dowiesz się jak zaprojektowad własny system zdarzeo. Nauczysz się wykorzystywad elastycznośd systemu zdarzeo Silverlight w projektowaniu logiki twojej aplikacji. Cel modułu Celem modułu jest przedstawienie koncepcji programowania z wykorzystaniem systemu zdarzeo i komend. Nadrzędnym celem jest zrozumienie różnic pomiędzy wyzwoleniem zdarzenia, jego obsługą oraz strategią roznoszenia informacji o jego zajściu. Uzyskane kompetencje Po zrealizowaniu modułu będziesz: wiedział czym są zdarzenia oraz jakie koncepcje programistyczne rządzą ich zachowaniem, potrafił wykorzystad siłę systemu zdarzeo komponentów Silverlight, rozumiał jak budowad, wyzwalad i nasłuchiwad własnych zdarzeo. Wymagania wstępne Przed przystąpieniem do pracy z tym modułem powinieneś: znad podstawy języka C# rozumied mechanizm delegowania metod,

Przygotowanie teoretyczne Przykładowy problem Chcesz zaprojektowad aplikację pozwalająca przetwarzad dokumenty tekstowe. Z każdym dokumentem wiążesz proste menu obsługujące operacje nao przeprowadzane. Niemniej chcesz zaprojektowad aplikację elastycznie, aby umożliwid przenoszenie fragmentów treści pomiędzy oknami, zapisywanie wszystkich dokumentów, zamykanie itp. Aplikację tego typu stworzyd można w sposób piękny inżynieryjnie albo w sposób ekstremalny (tzw. kod spaghetti). Niezależnie którą metodę wybierzesz powinieneś dopasowad się do wzorców informowania o zajściu określonych zdarzeo. Dodatkowo powinieneś umied tworzyd własne wzorce zdarzeo oraz metody je obsługujące. Przygotowanie teoretyczne Technicznie, zdarzenie to nic innego jak zmienna typu delegowanego poprzedzona słowem kluczowym event, np.: public event SimpleOne NaszEvent; Słowo kluczowe event pozwala na wywołanie delegowanego kodu tylko z poziomu właściciela zmiennej. Jeśli typ delegowany nie zwraca żadnej wartości, wtedy przy pomocy operatorów += oraz -= możemy zarejestrowad (wyrejestrowad) więcej niż jedną metodę. Delegowany kod wykonywany jest (zdarzenie jest wyzwalane) przy spełnieniu określonego warunku np.: if ( zdjęcia_wybrane.count > 0 ) NaszEvent(zdjęcia_wybrane); Podsumowując, system zdarzeo wykorzystuje w standardowy mechanizm delegowania kodu który znasz z C#. W poprzednim module poznałeś zdarzenia zdefiniowane w klasie UIElement odpowiedzialne za interakcję z kursorem myszy czy klawiaturą. W Silverlight zwyczajowo zakłada się że wzorzec delegacji posiada format gdzie: void NazwaTypu(Object sender, EventArgs arg) sender referencja do obiektu który wyzwala zdarzenie, arg pozwala przekazad informacje o specyficznych własnościach zdarzenia. Podobnie w zwyczaju jest umieścid metodę pozwalającą klasom potomnym wyzwolid zdarzenie (wzorzec OnEvent), czyli np.: protected void OnMojeZdarzenie(EventArgs arg) If (MojeZdarzenie!=null ) MojeZdarzenie(this, arg); Przykładem zdarzenia które wykorzystuje standardowe mechanizmy CLR jest LayoutUpdated klasy FrameworkElement, zdefiniowane jako: public event EventHandler LayoutUpdated Wyzwalane jest wtedy gdy zaszła zmiana wielkości lub położenia komponentu lub jego kontrolkidziecka. Mimo tego, że zdarzenie to ma prototyp: public delegate void EventHandler(Object sender, EventArgs e) Nie możemy zakładad, że sender wskazywał będzie na kontrolkę na która wykonała zmianę wyglądu. Zdarzenie to zawsze wyzwalane jest z pierwszym argumentem wynoszącym null. Zachowanie to tłumaczy się potrzebą generowania kodu który będzie bezpośrednio związany z kontrolką. Jeśli znasz

WPF (Windows Presentation Foundation) to pewnie zauważyłeś, że tam zdarzenie zawiera niepustą referencję na obiekt na którym zaszło. Dodatkowo jest to zdarzenie innego typu niż zwyczajowy EventHandler, jest to mianowicie RoutedEventHandler. Rozgłaszanie zdarzeń Niektóre zdarzenia po ich wyzwoleniu informują inne kontrolki o fakcie wyzwolenia zdarzenia. Proces ten nazywany rozgłaszaniem zdarzeo. Weźmy pod uwagę następujący fragment kody XAML: <StackPanel> <TextBlock Text= Wybierz tło /> <StackPanel> <TextBlock Text= Zwykłe > <Image /> <Image /> </StackPanel> <StackPanel> <TextBlock Text= Obrazy > <Image /> </StackPanel> </StackPanel> Definiuje on drzewo wizualne postaci: StackPanel TextBlock StackPanel StackPanel TextBlock Image Image TextBlock Image Rys. 1 Drzewo wizualne Jeśli na którymś z obiektów Image wyzwolono zdarzenie MouseLeftButtonDown wtedy oczywiście wykonany jest kod obsługujący to zdarzenie. Dodatkowo jednak to zdarzenie obsłużone jest na jego bezpośrednim ojcu, a następnie na ojcu ojca itd. StackPanel MouseLeftButtonDown TextBlock StackPanel StackPanel MouseLeftButtonDown TextBlock Image Image TextBlock Image MouseLeftButtonDown Rys. 2 Rozgłaszanie zdarzenia Strategia takiego rozgłaszania komunikatów w górę znana jest np. z WPF (pod nazwą bąbelkowania, ang. Bubling). Jest to jedyna standardowo wbudowana w Silverlight strategia rozgłaszania komunikatów.

Warto podkreślid, że o zajściu zdarzenia informowani są tylko bezpośredni rodzice. Proces rozgłaszania przypomina ścieżkę czyli inne kontrolki niż te leżące na ścieżce nie zostaną poinformowane o zajściu MouseLeftButtonDown. Częstym scenariuszem użycia jest obsługa zdarzenia tylko na ważnym panelu, który możemy ukryd po wybraniu któregoś elementu. Pojawiają się naturalne pytania: Jak znaleźd obiekt na którym zdarzeni zostało wyzwolone na początku ścieżki rozgłaszania? Czy rozgłaszanie można zablokowad? Technicznie zdarzenia które mogą być (nie wszystkie są) rozgłaszane dziedziczą z klasy RoutedEvent. Ogólny wzorzec delegacji ma postad: public delegate void RoutedEventHandler(Object sender, RoutedEventArgs e) Jedyną różnicą jest typ argumentu mamy tutaj mianowicie klasę RoutedEventArgs. Klasa ta dziedziczy z EventArgs, ale udostępnia nam własnośd OriginalSource. Odczyt możliwy jest zawsze i winien wskazywad na kontrolkę na której wyzwolono zdarzenie (początek ścieżki rozgłaszania komunikatu). Odpowiedź na pytanie jak zablokowad rozgłaszanie komunikatu nie jest tak łatwa. Niektóre typy argumentów eksponują własnośd Handled typu logicznego. Przypisanie tej własności wartości true skutkuje często zatrzymaniem rozgłaszania. Nieco dokładniej rozgłaszanie jest kontynuowane, ale kod wykonywany jest warunkowo (warunek to!handled). Jeśli rozgłaszania nie można powstrzymad przy pomocy Handled (bo np. nie istnieje taka własnośd), zawsze można porównad referencje sender oraz OriginalSource, pozwoli to wykonywad kod tylko na kontrolce na której zdarzenie zaszło. W Silverlight 4 nie można definiowad własnych zdarzeo rozgłaszanych. Można natomiast zaprojektowad własny system zdarzeo pozwalający na wykonanie podobnej strategii, więcej na ten temat znajdziesz w module Własności zależne i doczepiane. W poniższej tabeli zabrano standardowe zdarzenia których zajście jest rozgłaszane. Zdarzenie Typ argumentu Handled KeyDown KeyUp MouseLeftButtonDown MouseRightButtonDown MouseLeftButtonUp MouseRightButtonUp KeyEventArgs MouseButtonEventArgs (patrz moduł poprzedni) MouseMove MouseEventArgs NIE MouseWheel MouseWheelEventArgs TAK DragEnter DragLeave DragOver Drop DragEventArgs (patrz dalsza częśd modułu) GotFocus RoutedEventArgs NIE TAK TAK TAK

LostFocus Używając standardowego systemu zdarzeo Silverlight 4 pamiętad należy, iż implementacja kontrolki może mied wpływ na odziedziczony system zdarzeo. Standardowym przykładem jest kontrolka Button. Przycisk dziedziczy z klasy ButtonBase w której zdefiniowano nowe zdarzenie Click. Dodatkowo przycisk posiada własnośd ClickMode której można przypisad jedną z trzech wartości: Hover Click wyzwalany jest gdy kursor znajdzie się nad kontrolką, Press - Click wyzwalany jest gdy przyciśnięto lewy przycisk myszy, Release Click wyzwalany jest gdy zwolniono wcześniej wciśnięty przycisk myszy. Standardowe zdarzenie MouseLeftButtonUp zostanie wyzwolone tylko w przypadku pierwszym (Hover), pozostałe dwa automatycznie ustawiają własnośd Handled. Pokazuje to zmiany w strategii wyzwalania które mogą wprowadzad kontrolki na gruncie ich implementacji. Mimo tego, że delegacja Click jest typu RoutedEventHandler oraz argument posiada własnośd Handled, zdarzenie nie rozgłasza swego wyzwolenia. Obsługa przeciągnij i upuść Silverlight wspiera obsługę mechanizmu Przeciągnij i Upuśd (ang. Drag and Drop). W chwili obecnej przeciągad można lokalne pliki klienta do aplikacji. Jak wspomniano wcześniej mechanizm oparto zdarzenia rozgłaszane. Argument wszystkich metod jest typu DragEventArgs w szczególności eksponuje on własnośd Data. Własnośd zawiera referencję do obiektu implementującego interfejs IDataObject. Interfejs ten umożliwia wydobycie danych na potrzeby naszej aplikacji. Zdarzenia pozwalające obsłużyd przeciąganie to: DragEnter wyzwalane gdy nad powierzchnią kontrolki znalazł się obiekt możliwy do opuszczenia (można wtedy np.: wygenerowad podgląd tego co stanie się gdy obiekt będzie opuszczony), DragLeave wyzwalane gdy obiekt możliwy do opuszczenia znalazł się poza powierzchnią kontrolki, DragOver - wyzwalane gdy obiekt znajduje się nad powierzchnią kontrolki. Dodatkowo po opuszczeniu pliku nad powierzchnią kontrolki wywoływane jest zdarzenie Drop. Aby mechanizm działał nad powierzchnią kontrolki musi zostad ustawiona wartośd AllowDrop oraz kontrolka musi byd widoczna. Dostęp do danych za pośrednictwem interfejsu IDataObject, który w szczególności zawiera następujące metody: GetData pozwala wydobyd dane. Jedynym prawidłowym argumentem jest w chwili obecnej DataFormat.FileDrop. GetFormats zwraca format danej lub formaty do których można daną konwertowad. GetDataPresent informuje czy dane posiadają zadany format lub mogą byd do niego konwertowane Przykładowe wydobycie danych może odbywad się następująco: IDataObject dane = e.data; If (data.getdatapresent(dataformats.filedrop)) FileInfo[] pliki = data.getdata(dataformats.filedrop) as FileInfo[]; foreach (var plik in pliki)

Wzorzec komendy Ważnym elementem pozwalającym oddzielid cześd wizualną aplikacji od logiki biznesowej jest system komend. Komendy (and. Command) pozwalają na komunikację między kontrolkami nie tylko w obrębie ścieżki rozgłaszania komunikatu. Ogólnie rzecz ujmując w chwili zajścia określonego zdarzenia Silverlight może wywoład pewną metodę podobnie jak wywołuje się zwykłe zdarzenie. Skoro tak, to jaka jest różnica pomiędzy zwykłym zdarzeniem a komendą? Komendy mogą mied wpływ na element który je wykonuje (mogą np. zabronid wykonania). Inną istotną cechą jest możliwośd definiowania komend na podstawie interfejsów i danych. Nazwy komend wraz ich argumentami definiowane są z poziomu składni XAML, a szczegółowe znaczenie nadawane jest przez bieżącą implementację zdefiniowaną przez własnośd DataContext dziedziczoną z klasy UIElement. Komendy pozwalają na realizację wzorca projektowego MVVM (ang. Model-View View-Model) czy wzorca MVC (ang. Model View Controller), dzięki temu szczególnego znaczenia nabierają przy projektach większej skali. Kontrolki które wspierają komendy to: Button oraz HyperlinkButton. Posiadają one własności: Command typu ICommand interfejs implementujący komendę, CommandParameter typu Object argument przekazany komendzie. Interfejs ICommand ma postad: Public interface ICommand void Execute(Object Parameter); bool CanExecute(Object Parameter); event EventHandler CanExecuteChanged; Metoda Execute powinna zawierad kod wykonywany w chwili uruchomienia (wyzwolenia) komendy. Argumentem komendy w chwili wyzwolenia staje się CommandParameter. Metoda CanExecute uzyskuje ten sam argument co metoda Execute ale nie powoduje wykonania wyzwolenia komendy informuje czy dla tego argumentu można komendę wykonad. Gdy zwróci wartośd false, oba przyciski przejdą w stan wyłączony (tj.!enabled). Zdarzenie CanExecuteChanged wyzwolone zostanie wtedy gdy zmieni się wartośd metody CanExecute (np.: poprzednie argumenty były prawidłowe, a nowy argument jest niezrozumiały). Standardowy przypadek użycia to zamiana tła kontrolek na czerwony gdy podano nieprawidłowy argument. Silverlight nie wymusza stosowania określonego wzorca projektowego a tym samym nie dostarcza gotowych implementacji interfejsu ICommand. Posiadamy pełną swobodę projektowania. Można pokusid się o stworzenie złożonego systemu komend pozwalających np.: grupowad i wyzwalad inne komendy. Temat komend rozwinięty jest w module Łączenie danych i automatyzacja wyświetlania. Kontekst danych i odświeżanie zawartości Ważną klasę zdarzeo stanowią zdarzenia związane z odświeżaniem zawartości komponentów których zawartośd generowana jest na podstawie kolekcji. Ponieważ zagadnienie to jest blisko związane z budową systemu komend zarysujemy tutaj technikę tworzenia takich komponentów oraz odświeżania ich zawartości.

W klasie UIElement istnieje specyficzna własnośd DataContext. Własnośd ta najogólniej rzecz biorąc pozwala z dowolnym komponentem wiązad zbiór danych (np.: klasę). Tak utworzona przestrzeo danych widoczna jest przez wszystkie kontrolki dzieci komponentu któremu przypisano DataContext. Załóżmy, że posiadamy implementację następującego interfejsu: public interface WyborTla ; ICommand checkcommand set; get; ObservableCollection<DaneTestowe> data get; Z poziomu kodu XAML powinniśmy dołączyd nasza implementację do zasobów aplikacji, można uczynid to w poniższy sposób: <UserControl.Resources> <loc:testowyviewmodel x:key="testvm" /> </UserControl.Resources> Zasoby to nic innego jak słownik. Dołączony zasób powinien mied zdefiniowany domyślny konstruktor (bezargumentowy). Każdy zasób winien byd nazwany dzięki x:key. Tak opakowane dane możemy przypisad do kontekstu danych dowolnej kontrolki, np.: <Grid DataContext="StaticResource testvm"> </Grid> Zapis powyższy nakazuje wyszukanie zasobu o nazwie testvm oraz a następnie przypisanie tego zasobu jako wartości DataContext. Innym sposobem dostępu do danych jest wiązanie danych (ang. Binding). Na przykład jeśli kontrolkądzieckiem powyższego panelu Grid jest Button wtedy możemy z bieżącego kontekstu danych wybrad komendę której nazwę zawiera interfejs WyborTla, np.: <Grid DataContext="StaticResource testvm"> </Grid> <Button Command="Binding checkcommand" /> Użycie słowa Binding powoduje dowiązanie wartości Command to obiektu przechowywanego nie w zasobach ale w lokalnym kontekście danych. Dowiązanie wykonane zostanie na etapie uruchomienia. Więcej o zasobach i wiązaniu danych znajdziesz w module zasoby i wiązanie danych. Jednym z paneli które pozwalają na automatyzację pracy ze zbiorami elementów jest panel ListBox. Zawiera on własnośd ItemsSource którą możemy dowiązad do dowolnej kolekcji elementów. W poniższym przykładzie <ListBox ItemsSource="Binding data" > </ListBox> Kolekcja wyszukiwana jest w bieżącym kontekście danych. Komponent ListBox przegląda element po elemencie takiej kolekcji i do swojej zawartości dodaje kontrolkę powstałą na bazie wzorca. Wzorzec kontrolki, typu DataTemplate, należy przypisad własności ItemTemplate. Np.: <DataTemplate> <StackPanel> <TextBlock Text="Silverlight" />

<Image Width="200" Height="200" /> </StackPanel> </DataTemplate> Oznacza to, że wzorzec kontrolki składał się będzie z obiektu StackPanel na którym znajdzie się TextBlock a następnie Image. Więcej o wzorcach i stylach dowiesz się w module Style i automatyzacja wyświetlania. Najważniejsze z punktu widzenia jest to, że w chwili tworzenia dowolnej kontrolki na podstawie ItemTemplate jej kontekst danych rozszerzany jest o dane elementu kolekcji przypisanej do ItemSource. Zatem skoro kolekcja data jest typu ObservableCollection<DaneTestowe>, to każda budowana kontrolka będzie miała dostęp do danych elementów kolekcji. Załóżmy, że klasa DaneTestowe ma postad: public class DaneTestowe public String nazwa; public Uri uri; Wtedy prawidłowe jest wiązanie: <ListBox ItemsSource="Binding data"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="Binding nazwa" /> <Image Width="200" Height="200" Source="Binding uri" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> Dochodzimy zatem do meritum sprawy. O ile wyświetlenie nie stanowi problemu, to co się stanie gdy kolekcja data zmieni swoją zawartośd? Ze względów wydajnościowych zawartośd kolekcji data jest wstępnie klonowana, dopiero później rozpoczyna się proces Budowy kontrolek. Oznacza to, że jeśli zawartośd kolekcji zmieni się, może to pozostad bez skutku ekranowego. Z jednej strony można dzięki temu przygotowad nową tablicę danych podczas gdy użytkownik widzi poprzednią zawartośd (np.: etap ładowania danych), ale z drugiej kiedyś należy poinformowad ListBox aby zaktualizował zawartośd. Na szczęście typ ObservableCollection implementuje zdarzenie CollectionChanged. Ponieważ na etapie wiązania ListBox deleguje kod do obsługi tego zdarzenia. Każda zamiana zawartości kolekcji skutkuje zamianą zawartości komponentu ListBox. Klasa ListBox umożliwa wybór jednego lub wielu elementów, zaimplementowano bowiem zdarzenie SelectionChanged. Dostęp w wybranego elementu uzyskuje się przez własnośd SelectedItem. Dostęp do grupy wybranych elementów możliwy jest przez własnośd SelectedItems.

Przykładowe rozwiązanie Chcemy zaprojektowad wyszukiwarkę teł do foto-książki. Tła pobierane mają byd domyślnie z serwera niemniej aby nie pobierad wszystkich teł natychmiast chcemy pobrad tylko ich nazwy wraz z towarzyszącym im URI do pliku. Użytkownik wprowadzi fragment nazwy która go interesuje i będzie musiał wcisnąd przycisk aby obrazy pobrad obrazy pobrad. Przy okazji wykonamy pierwszy krok projektując kod testowy przypominający wzorzec MVVM. Załóżmy, że mamy do zaimplementowania interfejs WyborTla (pojawił się wcześniej w przygotowaniu praktycznym), następującej postaci: public interface WyborTla ; ICommand checkcommand set; get; ObservableCollection<DaneTestowe> data get; event EventHandler BackgroundSelected; void PictureSelected(String name); Komenda checkcommand realizowała będzie wybór tła, data będzie punktem wejścia do danych wyświetlanych przez ListBox, a BackgroundSelected będzie to zdarzenie wyzwalane gdy wybrano tło. Załóżmy, że to klasa danych implementowała dziedziczyła będzie z ObservableCollection, np.: public class TestowyViewModel : ObservableCollection<DaneTestowe>, WyborTla public TestowyViewModel() DaneTestowe[] dane = new DaneTestowe("Tulipany", new Uri("Tulips.jpg", )), ; new DaneTestowe("Pingwiny", new Uri("Penguins.jpg", )) Ponieważ tworzymy wersję testową powinniśmy utworzyd dane testowe. Tworzona komenda powinna posiadad referencje do klasy TestowyViewModel oraz, dla potrzeb prototypu, referencję do kolekcji danych z których mamy wybrad tło. Nazwijmy klasę komendy CheckCMD, może ona mied definicję: protected class CheckCMD : ICommand public event EventHandler CanExecuteChanged; private DaneTestowe[] t; private TestowyViewModel tloi; public CheckCMD(DaneTestowe[] tab, TestowyViewModel tloi) t = tab;

this.tloi = tloi; Metoda CanExecute powinna zadziaład wyłącznie wtedy gdy argumentem jest niepusty łaocuch. Metoda ta winna stwierdzid czy istnieją tła posiadające w nazwie podany fragment znaków. Przykładowo: public bool CanExecute(Object param) if (param is String) String selector = param as String; if (selector!="") foreach (DaneTestowe dt in t) return false; if (dt.nazwa.contains(selector)) return true; Odrobinę ciekawsza jest metoda Execute która winna dodad do danych wszystkie elementy które posiadają w nazwie zadany ciąg znaków, przykładowo: public void Execute(Object param) String selector = param as String; if (selector!= "") tloi.clear(); foreach (DaneTestowe dt in t) if (dt.nazwa.contains(selector)) tloi.add(dt); Pozostaje zaimplementowad dostęp do danych, czyli: public ObservableCollection<DaneTestowe> data get return this;

Właśnie zakooczyliśmy budowę zaplecza naszego rozwiązania. Kolejny krok budowa części wizualnej. Większośd zaprezentowano już w części teoretycznej, teraz więc pokusimy się o przedstawienie znaczącej zawartości kontrolki: <UserControl.Resources> <loc:testowyviewmodel x:key="testvm" /> </UserControl.Resources> <StackPanel DataContext="StaticResource testvm" > <ListBox ItemsSource="Binding data" > <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="Binding nazwa" /> <Image Source="Binding uri" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <TextBox Name="textBox" VerticalAlignment="Top" Text="wpisz fragment nazwy" /> <Button Content="Pobierz" Name="Przycisk" Command="Binding checkcommand" CommandParameter="Binding Path=Text, ElementName=textBox"/> </StackPanel> Jedyna zmianą jest wiązanie argumentu komendy z własnością Text komponentu o nazwie textbox. Pozostaje obsługa samego wyboru tła. Realizujemy to obsługując zdarzenie SelectionChanged zależnie od potrzeb aplikacji możemy wyzwolid zdarzenie BackgroundSelected z jednym obrazem tła albo z wieloma. Rys. 3 Rezultat do ulepszenia przez grafika

Porady praktyczne Często założenie o sposobie wyzwalania zdarzenia zależy od implementacji kontrolki. Brak wyzwolenia albo wyzwolenie w innym momencie, to podstawowe problemy implementacyjne (patrz Button) dlatego uważnie badaj kontrolki których używasz. Problemem są różnice w wyzwalaniu komunikatów pomiędzy WPF a Silverlight, np.: WPF zdarzenia MouseEnter oraz MouseLeave wyzwalane są nawet w przypadku nieruchomego kursora (wystarczy, że np. animowany element znajdzie się pod kursorem myszy) natomiast w Silverlight zdarzenia te wyzwalane są tylko w przypadku poruszania kursorem myszy. Gdy nie jesteś pewien działania a znasz już WPF zaprojektuj odpowiedni test w Silverlight. Nie zawsze zdarzenia typu RoutedEventHandler rozgłaszają informacje o wyzwoleniu. Na potrzeby mechanizmu Drag and Drop powinieneś ustawid parametr windowless na wartośd true. Czasem będziesz musiał dopisad wrapper w JavaScirpt poza aplikacją Silverlight aby przenoszenie działało prawidłowo. Komendy to doskonały mechanizm rozgłaszania wyzwolenia zdarzenia. Przykładem komend wbudowanych jest mechanizm Kopiuj/Wklej. Uwagi dla studenta Jesteś przygotowany do realizacji laboratorium jeśli: Rozumiesz pojęcie wyzwalania zdarzenia, Rozumiesz pojęcie komendy oraz jej wyzwalania, Potrafisz zakooczyd proces rozgłaszania zdarzenia, Potrafisz dowiedzied się który komponent wyzwolił zdarzenie rozgłaszane, Umiesz zaprojektowad kod wykorzystujący system komend, Potrafisz zaprojektowad własne zdarzenia, Potrafisz wyzwolid własne zdarzenia, Wiesz jak działa mechanizm przeciągnij i upuśd. Pamiętaj o zapoznaniu się z uwagami i poradami zawartymi w tym module. Upewnij się, że rozumiesz omawiane w nich zagadnienia. Jeśli masz trudności ze zrozumieniem tematu zawartego w uwagach, przeczytaj ponownie informacje z tego rozdziału i zajrzyj do notatek z wykładów.

Dodatkowe źródła informacji Więcej o zdarzeniach w Silverlight 4 znajdziesz: http://msdn.microsoft.com/en-us/library/cc189018%28v=vs.95%29.aspx Więcej o sposobach przygotowania komend znajdziesz: http://msdn.microsoft.com/en-us/library/ff921126%28pandp.20%29.aspx

Laboratorium podstawowe Zadanie 1 (czas realizacji 20 minut) Twój nowy klient poprosił o prototyp interfejsu do wyboru odcienia płytek podłogowych. Jego życzeniem jest paleta kolorów rozłożonych dookoła wspólnej osi obrotu przesuwając kursor obracasz elementy. Zatwierdzasz wybór odpowiednim przyciskiem. Ponieważ jego firma udostępnia oprogramowanie na ekranach dotykowych starej konstrukcji (ang. SingleTouch) możesz wykorzystad tylko zdarzenia MouseLeftButtonDown, MouseLeftButtonUp oraz MouseMove.

Zadanie 2 (czas realizacji 25 minut) Twój główny klient pragnie wzbogacid oprogramowanie o menu służące do wybory rodzaju pisma. Jednak nie chce klasycznego menu gdzie osobno wybiera się czcionkę, jej wielkośd, styl oraz kolor. Przygotował pieczołowicie tablice danych krojów które jego odbiorcy będą mieli do wyboru. Wizualna cześd menu powinna wyświetlad podgląd kroju na tekście przykładowym. Masz jak zawsze niewiele czasu na realizację tego zadania.

Laboratorium rozszerzone Zadanie 1 (czas realizacji 40 minut) Zaprojektuj typ generyczny ułatwiający pracę z komendami. Typ powinien byd tworzony na podstawie klasy oczekiwanego argumentu. Dodatkowo powinno byd możliwe rejestrowanie metod wykonanych przy okazji wykonania metody Execute. Zadanie 2 (czas realizacji 45 minut) Zaprojektuj typ generyczny ułatwiający pracę z komendami złożonymi. Komenda złożona winna wykonywad kolekcję komend prostych. Wskazówka. Możesz założyd, że jeśli co najmniej jedna komenda może byd wykonana to również komenda złożona może byd wykonana. Natomiast Execute wykonaj tylko na komendach dla których CanExecute jest prawdą. Zadanie 3 (czas realizacji 90 minut) Do zadania 3 z poprzedniego modułu (foto-książka) dołącz możliwośd przeciągania zdjęd z zasobów użytkownika. Wskazówka. Powinieneś zaimplementowad alternatywę do przycisku dodawania zdjęd. Zadanie 4 (czas realizacji 90 minut) Do zadania 3 z poprzedniego modułu (foto-książka) dołącz możliwośd wyboru teł. Wskazówka. Dowolny panel gdy jest niewidoczny (!Visible), nie bierze udziału w przydziale miejsca. W ten sposób schowasz Panel wyboru tła gdy nie będzie potrzebny.