wtorek, 29 czerwca 2010

Blend 4 - ułatwienia dla MVVM i w designie

By zrobić show z Blenda 4 można zawsze na pierwszy ogień rzucić kontrolkę PathListBox, dynamiczny layout, efekty przejść, warunkowe zachowania… Rzeczy związane z codziennym pisaniem aplikacji, różnymi problemami w designie nie wydają się już tak ciekawe… A tymczasem niesłusznie, bo … są to sprawy, które dotyczą … prawie każdego programisty, który ma współpracować z grafikiem lub … jeśli sam pełni podwójną rolę, chce zyskać na czasie i na wygodzie.

Zacznijmy od wzorców projektowych, a konkretne od MVVM, który stał się wręcz standardem w przypadku aplikacji w Silverlight i WPF. W nowym Blend poczyniono różne udogodnienia w tym kierunku.

Jeśli chodzi o predefiniowane szablony, to dostajemy nowy rodzaj projektu WPF/Silverlight Databound Application. Dostajemy stworzony na wstępie szkielet view modelu, widok, przykładowe dane, wywołanie metody… View modele nie zakładają konkretnej platformy do ich budowania.  Jak dla mnie bardziej przydatnym na co dzień i w pełni wystarczającym jest szablon elementu UserControl with ViewModel. Za jego pomocą tworzymy, to co w wyżej wymienionym szablonie projektu jest predefiniowane na przykładzie, czyli szkielet view modelu i związany z nim widok. Aplikacja nie musi być koniecznie rodzaju DataBound Application

01_MVVM_02

Wzorzec MVVM zakłada wywoływanie logiki poprzez bindowanie komend w widoku. W Silverlight 4 tylko Button, HyperlinkButton i MenuItem w menu kontekstowym przewidują komendę jako swoją propercję do zbindowania. A co z innymi zdarzeniami? A co z innymi kontrolkami i obiektami wizualnymi? A co jak programista nie miał specjalnej ochoty pisać komend i część funkcjonalności mamy tylko w postaci metod? W Blendzie 4 wystarczy…  zrobić drag & drop obiektu komendy lub metody z panelu Data na obszar roboczy.

01_MVVM_06 - Mod

Bardzo szybko i prosto się to robi, ale … nie ma w tym żadnej magii. Jeśli sprawa nie dotyczy odpowiedniej kontrolki i komendy, to designer zamiast bindingu do komendy wstawia nam akcję wywołania komendy lub metody wyzwalaną triggerem na typowym dla danego obiektu zdarzeniu (które - podobnie jak i cały trigger - możemy szybko zmienić na inny rodzaj). Każdy to sobie może sam oczywiście zrobić, ale od tego mamy właśnie narzędzia, by ten proces sobie maksymalnie skrócić …

01_MVVM_07

Przykładowe dane - kolejne zagadnienie, które pojawi się na pewno na styku programista-designer. Grafik potrzebuje przykładowych danych, aby zobaczyć jak będzie wyglądać całościowo UI, bez tego nie widzi w pełni swojego końcowego dzieła zanim nie uruchomi aplikacji, a to jest dość uciążliwe. Przykładowe dane możemy łatwo tworzyć od Blenda 3, ale w typowym scenariuszu nie jest to najwygodniejsze… Dlaczego? Bo zazwyczaj mając napisaną przez kogoś aplikację nie potrzebujemy definiować już struktur, a raczej wykorzystać już istniejące, ale z przykładowymi, niekoniecznie nawet poprawnymi biznesowo wartościami. Po drugie programiści często skupiają się wyłącznie na pisaniu kodu i nie przykładają wagi do tego, aby tworzone przez nich struktury danych i view modele były przyjazne grafikowi w czasie designu. 

Możemy tym wszystkim … nie martwić się, jeśli używamy nowego Blenda. Została dodana opcja tworzenia przykładowych danych na podstawie danej klasy. Co więcej propercje nie muszą mieć setterów, a klasy publicznych konstruktorów, … Programiści nie muszą myśleć o przyjazności dla designu, wszelkie braki wyrównuje narzędzie. Generowany jest xaml z instancjami obiektów odpowiadających naszym strukturom danych wypełnionych przykładowymi wartościami, które możemy też edytować. Dla bindingu w czasie designu jest to w pełni wystarczające.

01_MVVM_09

Jeśli korzystając z powyższej metody utworzyliśmy sobie instancję naszego view modelu, to możemy przeciągnąć ją na korzeń danego widoku. Utworzy się d:DataContext, czyli DataContext obowiązujący tylko na okres designu. Jest to wygodne, bo jest w pełni transparentne dla działania aplikacji w runtime.

01_MVVM_13 - Mod

Jeden ruch i widzimy wszystkie potrzebne dane w czasie designu.

01_MVVM_14

Kolejne zagadnienie - resourcy dostępne tylko w czasie designu. Pewnie wielu bez entuzjazmu powie, że nie widzi zastosowania czegoś takiego u siebie w codziennej pracy. Nic bardziej mylnego! Ileż to razy piszemy złożone aplikacje, w których pewne dane są doczytywane w czasie runtimu z innych modułów. MEF i wszelkiej maści kontenery są nieocenione, jeśli chodzi o elastyczność i luźne powiązanie architektury. Jednak to co jest powodem to zadowolenia programisty, nie musi być już powodem zadowolenia dla grafika. Grafik zacznie tutaj przeklinać, jeśli okaże się, że słownik ze skórką aplikacji jest doczytywany w kodzie w runtimie (który nie jest analizowany) i nie widać go w czasie designu, a Blend sypie wyjątkami i ostrzeżeniami.

Co zrobić? Zawsze można pogonić programistę, by nam takich przekombinowań nie robił, ale używając nowego Blenda możemy sprawić, że wilk będzie syty i owca cała. Wystarczy, abyśmy załączyli sam słownik ze skórką jako element projektu. Blend po wykryciu nie rozwiązanych odniesień do zasobów i widząc słowniki w projekcie, sam … wyświetli okienko dialogowe, czy nie chcielibyśmy widzieć, któregoś z dostępnych słowników na czas designu.  Wtedy dołączy wybrany przez nas słownik do specjalnego słownika DesignTimeResources.xaml trzymanego w katalogu Properties. Tu chciałbym jeszcze raz podkreślić, że cały zabieg nie wpływa w żaden sposób na działającą w runtime aplikację, jest to tylko udogodnienie na czas designu.

Jakieś przykłady z życia wzięte? Ze swojej autobiografii mogę wspomnieć problem jaki wiązał się z pobieraniem z weba skórek i ładowanie ich w czasie runtime do aplikacji. W ówczesnych czasach kończyło się na ingerencji w App.xaml i kopiowaniem skórki do projektu. Dziś też ją byśmy ją skopiowali (nie ma wszak cudów, by pracować na skórce bez jej importu), ale byłoby to zrobione doskonalej. Mało tego, podmieniając załączone słowniki w słowniku dla designu możemy w designie podmieniać różne skórki bez ingerencji w działanie aplikacji. Inny przykład to sytuacja właśnie z MEF, gdy po jego zastosowaniu definicja słownika z App.xaml została zamieniona na dodawanie słownika w kodzie. Tej funkcjonalności użyłem jako jednej z pierwszych w Blend 4, co zostało wymuszone przez zaistniałą sytuację.

01_MVVM_15

A oto moja prosta aplikacyjka w pełnej krasie, w której użyłem opisane wszystkie w tym poście nowe funkcjonalności Blenda. Jak widać dane w runtime różnią się nieco od danych pokazywanych w designerze. Przyciski natomiast wyglądają tak samo dzięki słownikowi dodanemu na czas designu.

01_MVVM_17

Źródła prezentowanego przykładu, jak i opis powyższych zagadnień w nieco innej postaci zostały opublikowane tutaj.

piątek, 25 czerwca 2010

Zachowania w Blend 4 - więcej możliwości, mniej kodu!

Pragnę dzisiaj poruszyć tematykę behaviorów w nowym Blendzie. W stosunku do Blenda 3 mamy więcej predefiniowanych zachowań, możemy bindować ich propercje, określać warunki kiedy się mają wykonywać.

Warunkowe zachowania pozwalają nam zaoszczędzić pisania kodu w pewnych przypadkach. Ważna nowość, ale ja dziś poświęcę więcej uwagi innej nowości – Data Store.

Data Store pozwala nam łatwo współdzielić dane między różnymi częściami aplikacji (np. różnymi ekranami w przypadku nawigacji). Zarówno jego definiowanie, jak i korzystanie z niego (dzięki odpowiednim zachowaniom) nie wymaga pisania żadnego kodu! Teraz designer może dużo więcej! Ma to zwłaszcza duże znaczenie  przy szybkim budowaniu prototypu aplikacji w SketchFlow, choć jest to w pełni uniwersalny mechanizm.

Spójrzmy na poniższe 2 screenshoty pokazujące aplikację przed i po zalogowaniu do niej użytkownika.

01_ConBehDataStore_03 01_ConBehDataStore_06

Odpowiem teraz krótko na dwa pytania. Jak przekazać nazwę użytkownika z pola tekstowego po zalogowaniu do następnego ekranu? Jak wykryć, że użytkownik się zalogował i w odpowiedzi na to wyświetlić górne menu?

Aby przekazać nazwę użytkownika trzeba w momencie kliknięcia na przycisk Login zapisać napis w zmiennej w Data Store. Realizuje to SetDataStoreValueAction, w której wskazujemy (bądź kontekstowo tworzymy) interesującą nas propercję w Data Store oraz podajemy dla niej wartość (tutaj poprzez binding do propercji Text TextBox’a z nazwą użytkownika).

01_ConBehDataStore_02

Zapamiętaną informację chcemy teraz wyświetlić na stronie Home. Nic prostszego! Najszybciej osiągniemy to przeciągając nazwę propercji Data Store z panelu Data na miejsce w UI, gdzie chcemy to wyświetlać. Jeśli upuścimy propercję na kontrolce, to Blend nam zaproponuje utworzenie bindingu dla domyślnie bindowanej propecji kontrolki z możliwością wybrania innej. Jeśli miejscem upuszczenia będzie kontener layout’u, to Blend sam stworzy TextBlock’a i zbinduje jego propercję Text.

01_ConBehDataStore_05 - Mod

Nasuwa się tutaj pytanie, czym fizycznie jest Data Store? Kod klasy DataStore (w tym jej definicje propercji i wartości)  jest generowany przez kreator Blend’a. Następnie Blend sam automatycznie  tworzy sobie obiekt tej klasy globalnym resource’m na poziomie całej aplikacji. Klikając użytkownik może tego wszystkiego nie być świadomy! Tu wielu pewnie powie, że to nic nadzwyczajnego i że sami mogli zawsze to sobie zrobić. Zgoda, ale to właśnie dzięki wygodnej automatyzacji możemy mówić o nowej jakości! Dodatkowo zawsze mamy możliwość dokonywania zmian w definicji Data Store poprzez panel Data.

01_ConBehDataStore_01

Teraz odpowiem na pytanie jak wykryć zmianę wartości danej propercji w Data Store. Należy w interesującym nas miejscu w UI użyć DataStoreChangeTrigger i wskazać mu interesującą nas propercję Data Store. W naszym przypadku ten trigger monitoruje zmianę logicznej propercji mówiącej czy użytkownik jest zalogowany (jest ustawiana na True przy logowaniu). Następnie wykonywana jest akcja ustawienia propercji Visibility panelu menu na wartość Visible, pod warunkiem, że nasza propercja IsAuthenticated w Data Store ma wartość True.

01_ConBehDataStore_04

Poruszane dziś zagadnienia (ale nieco w innym ujęciu), związane z nimi linki oraz prezentowany przykład opublikowałem także tutaj.

niedziela, 20 czerwca 2010

Blend 4 - zaskakujące efekty z FluidMoveBehavior

Dzisiaj chciałbym napisać o tym, o czym nieraz wspominałem od czasów ostatniego MIX’a, ale nie było okazji tego w szerszym gronie wyartykułować. Mianowicie chodzi mi o efekt, który nazwałem “wyskakującym krzesłem” od przykładu, który zazwyczaj go demonstruje.  

O co chodzi z tym krzesłem, czyż nie umiem już posługiwać się Blendem?  Tak zapewnie niejeden czytający tego posta sobie pomyśli. Już wyjaśniam.

Chodzi o wyjeżdżające krzesło na szczegółach elementu, po tym jak wybierze się dany element na liście. Nie byłoby w tym nic zaskakującego, gdyby nie to, że krzesło szczegółów wyjeżdża wprost z … krzesła na elemencie listy! Skąd krzesło szczegółów zna dokładnie i precyzyjnie pozycję odpowiadającego mu krzesła na danym elemencie listy? To są zupełnie inne obszary UI!

01_FluidMoveBehavior_MasterDetails_03 - Mod

Cały patent kryje się w nowych możliwościach FluidMoveBehavior, który potrafi animować teraz nie tylko sam element, ale także zbindowane dane. Pozycja konkretnych obiektów danych jest znajdowana na ekranie i to ona jest uwzględniana w animacji. Widzimy, że jak będziemy animować dany obiekt z danymi, a nie jego konkretną wizualną reprezentację, to nasze zadanie stanie się dużo prostsze. FluidMoveBehavior używany jest w gridzie ze szczegółami elementu i trzeba mu przekazać pozycję startową, którą jest położenie krzesła na danym elemencie listy. Pozycję startową krzesła dla danego obiektu danych rejestrujemy za pomocą FluidMoveSetTagBehavior w szablonie elementu listy. Ta informacja jest umieszczana niejawnie w data store, a potem jest wyciągana przez FluidMoveBehavior, który wtedy już wie, jak ma animować krzesło reprezentujące dany obiekt. W tym miejscu trzeba dodać, że możemy przebieg animacji modyfikować za pomocą dowolnej easing function, a całość odbywa się bez napisania linijki kodu ze strony użytkownika!  Jest to piękny przykład, pokazujący jak w uniwersalny sposób można zamknąć kawałek kodu, by innym żyło się lepiej.

A jak zrobić, by elementy wyjeżdżały płynnie z jednej listy i w wjeżdżały w odpowiednie miejsce na drugiej?  Nic prostszego! Wystarczy tylko w obu listach w szablonie panelu umieścić FluidMoveBehavior, tak by animował dzieci kontenera pobierane z data context’u.

02_FluidMoveBehavior_ListToList_03

Ciekawe efekty można osiągnąć używając LayoutStates na elementach listy, w której w kontenerze osadzony jest FluidMoveBehavior. Wtedy wszystko jest w ruchu, wszystko żyje, wszystko się zmienia. Zmienia się tworzony element przy jego dodawaniu do listy, ale także sama lista stopniowo rezerwuje dla niego miejsce. Podobnie może się dziać przy usuwaniu elementu z listy.

Więcej praktycznych szczegółów, przydatne linki oraz wszystkie przykłady zamieściłem tutaj.

środa, 16 czerwca 2010

Blend 4 - niebanalny layout bez linijki kodu!

Pisanie o nowym Blendzie rozpocznę od rzeczy moim zdaniem bardzo istotnej i dość przełomowej w stosunku do dotychczasowych możliwości - od layoutu wzdłuż dowolnego kształtu.

Do tej pory grafik musiał prosić programistę, aby ten napisał mu kod realizujący layout wzdłuż zadanej krzywej. Miał też utrudniony podgląd, by od razu móc wypróbować swoje pomysły. Jak się zmieniała koncepcja designu, programista znów musiał zmieniać kod. Czy nie lepiej przerzucić tworzenie złożonych krzywych na grafika, który najlepiej będzie wiedział, co chce osiągnąć i by mógł sobie łatwo zmieniać wygląd bez żadnego pośrednika?

Otóż w nowym Blendzie można, a jest to realizowane przy użyciu kontrolki PathListBox.

PathListBox układa elementy wzdłuż ścieżki lub ścieżek (a dokładniej mogą być to: Path, Shapes - dotychczasowe i nowe lub … dowolny wręcz element). Poprzez różne parametry mamy dość duży wpływ na efekt końcowy naszej pracy.

02_MultiplePaths

PathListBox (Blend SDK) uzupełnia też braki w samym Silverlight. Dzięki niemu wreszcie łatwo zrobimy animację i napis po dowolnej ścieżce.

Animacja po ścieżce polega na animowaniu parametru Start dla ścieżki w PathListBox. Dzięki temu widzimy, że obiekty na ścieżce się przesuwają.

03_MotionPath

Rozmieszczenie napisu wzdłuż ścieżki robimy poprzez zbindowanie stringa do ItemsSource PathListBox’a. W .NET string to kolekcja liter, ot cała tajemnica sukcesu! Jak dodatkowo wprawimy w ruch ścieżkę, to możemy tanio uzyskać całkiem niezły bajer.

04_TextOnPath

Bardzo łatwo możemy też sprawić, by np. rozmiary i przezroczystość elementów zależały od ich położenia na ścieżce.

05_PathListBoxItem_02

To nie wszystko! Usiądź, weź krzesło, zrób karuzelę nowoczesną! Dzięki rozszerzeniom dla PathListBox’a opublikowanym przez team Blenda można łatwo osiągać jeszcze bardziej zaawansowane efekty wizualne!  Teraz zrobienie np. nowoczesnej przeglądarki produktów to kwestia kilku kliknięć. Pamiętajmy, że PathListBox obsługuje dane podobnie jak ListBox, elementy nie muszą być podawane “na sztywno”, można bindować do kolekcji dowolnych obiektów.

Kto nie kupi krzesła w taakim sklepie?

06_PathListBoxUtils_03

Więcej szczegółów, przydatne linki oraz przykłady zamieściłem tutaj.

czwartek, 10 czerwca 2010

Silverlight 4 RTW - odświeżone przykłady + podsumowanie

Ostatnio zaktualizowałem wszystkie swoje wcześniejsze przykłady z Silverlight 4 Beta do wersji RTW (patrz Silverlight 4 RTW Samples - part I i part II).  Dodatkowo wzbogaciłem je o demonstracje większości nowych funkcjonalności, jakie pojawiły się w wersji RC. Mam więc dość mocne podstawy, by podzielić się obecnie pewnymi ciekawostkami i refleksjami na temat Silverlight 4 RTW.

Zacznijmy od kamery internetowej. Aplikacja FaceLight z codeplex z podstawianiem twarzy małpy rządzi! Nie ja pierwszy ją wyszukałem i pewnie nie ostatni, ale bawiąc się kamerą nie mogłem się i ja powstrzymać …

mk-monkey - cl

Co do wydruków to pewnie znajdzie się wiele przeciwników. Pod różnymi względami nie są doskonałe, ale przy pewnej determinacji można zrealizować wydruk wielostronicowy. Mamy informację o rozmiarze wydrukowanej strony, więc jakoś sobie poradzimy.  Jest to pokazane zresztą w training kicie i nie tylko. Ja też mam swój przykład od czasów bety, który po drobnych zmianach nadal jest aktualny.

Myślę, że należy zwrócić uwagę na atrybuty design-time wykorzystywane w data bindingu oraz przykładowe dane w Visual Studio 2010. Przy czym obecnie sami decydujemy, czy przykładowe dane w designie zostaną utworzone z naszych typów przy wywołaniu naszych konstruktorów czy też zostaną utworzone substytuty naszych typów. Możemy też używać bindingu w designie do samego typu bez zainicjalizowanych danych (czy to przez konstruktor czy z przykładowych danych), ale moim zdaniem lepiej jednak jest jeśli jakieś sensowne dane widzimy w designie.  Jeszcze jedno - w dokumentacji wyraźnie pisze, że atrybuty design-time nie mają żadnego wpływu na aplikację w run-time. Tak więc usuwanie atrybutów design w imię optymalizacji aplikacji nie ma po prostu żadnego sensu.

Kolejną rzeczą ciekawą jeśli chodzi o binding jest CollectionViewSource, a to dlatego, że implementuje interfejs ICollectionView, który jest specjalnie traktowany przez binding. Wtedy w scenariuszu master-details możemy używać skróconych ścieżek z pominieciem jawnego wskazania aktualnie zaznaczonego elementu.

Co do RichTextBox’a, to szkoda że serializacja bogatego tekstu nie uwzględnia kontrolek UI. Ciekawostką jest, że po zamknięciu ChildWindow, kontrolki w trybie edycji się … odblokowywują. 

W trusted out of browser zabawa z własną ramką okna może sprawić dużo przyjemności. Nareszcie możemy sami zapanować nad przyciskami okna, jego przeciąganiem i skalowaniem, a jednocześnie nadać mu oryginalny i niebanalny wygląd.

Trusted_OOB_CustomChrome

Szkoda, że obsługa COM nie jest pełna. Parametry nazwane nie są obsługiwane i przykład z czasów bety, który operował na wykresie w Excelu wstawianym do Worda obecnie przestał działać.

Kolejną rzeczą o której chciałbym wspomnieć to NetTcp binding w WCF obsługujący komunikację dwustronną. Tutaj jest taki przykład jeszcze z czasów MIX’a, w którym są przesyłane screenshoty z kamery webowej, co imituje transmisję video w chacie. Przykład może nie idealny, ale go lubię.

WCF_Video_Chat

Myślę, że warto wspomnieć też o WCF Data services i protokole OData. Oprócz wielu takich funkcjonalności jak stronicowanie, projekcja, ma też wydajną obsługę strumieniowania danych binarnych dużego rozmiaru. Pamiętajmy też, że w Visual Studio 2010 możemy korzystać z okna DataSources. Nie jest ono wyłącznie dedykowane dla WCF RIA Services.

WCFDataServices_DataSourcesWindow

Ostatnią rzeczą, o której chciałbym dzisiaj wspomnieć to Silverlight Toolkit, a konkretnie kontrolka menu kontekstowego i nowa – w mojej ocenie znacznie lepsza - obsługa themes. Niejawne stylowanie jest tu już wykorzystywane. Mamy też nową themę z ustawieniami z systemu operacyjnego.

Toolkit_Themes_Menu_Changing

Na zakończenie powiem, że … warto zaznajomić się z nowymi możliwościami narzędzi designera dla Silverlight 4 w Visual Studio 2010. Mamy m.in wyszukiwanie zasobów i spore udogodnienia w edycji panelu Grid!  Najlepiej tutaj obejrzeć 27 odcinek serialu w Silverlight TV, a i tak nie pokazuje on wszystkiego.