• This is a usual time of the year for summaries so let’s keep the tradition alive and write one. Here’s my 2017 achievements split between months. January Blogging for 18 days straight – nothing near gutek’s achievement (whole year!) but still a nice streak Microsoft MVP title (thx Konrad Kokosa for pointing this one ;)) February […]

  • “Advent of Code is a series of small programming puzzles for a variety of skill levels.” Each day was a fun an interesting coding challenge. I’ve decided to practice and code this in python to learn the skill. Some of them might not be the best python scripting as I was short on time in […]

  • Some time ago I’ve attended a .net developer days 2017 conference. I was quite busy since (traveling, teaching .net, working) that only now I got some time to share some thoughts about it. As a bonus I’m including a short interview I did during the event. I need to state here, just to be clear, […]

  • We developers don’t like documentation. We don’t like to read it, and we even more we don’t like to write it. But sometimes it is worth to read it. Like when you find out that by using datetime in SQL DB you got a milliseconds precision but only if it ends on 0,3,7 (link). That […]

  • In the previous post we’ve removed some of the technical debt that could be found in our NetDeveloperPoland Website application. In this one we will remove it even more. We can even maybe reach a B? Let’s see where we’ll end up at the end of this part.

Po powrocie z Norwegii czas powrócić do pisania o WPF :).

Dziś krótka i prawdopodobnie jedna z ostatnich lekcji. Do omówienia zostało nam sposób dostarczenia naszej aplikacji do klienta.
Jakie zatem mamy opcje? Windows Installer oraz ClickOnce.

Nie będę za bardzo skupiał się na różnicach pomiędzy nimi, gdyż nie ma tu nic innego w stosunku do aplikacji WinForms. Warto przypomnieć tylko, że ClickOnce jest odpowiedni do środowisk ‘partial-trust’, uruchamianie z adresu zdalnego oraz ma wbudowany mechanizm aktualizacji.

Windows Installer

Aplikację napisaną w WPF możemy tak jak dotychczas dostarczyć za pomocą Windows Installera. Nie różni się to od znanego nam przypadku z WinForms. Warto tylko, zauważyć, iż nie bardzo ma sens dostarczanie aplikacji XBAP w ten sposób. Wymagałoby to, aby XBAP był uruchamiany w trybie ‘full-trust’, co z racji specyfikacji tego rozwiązania jest niemożliwe.

ClickOnce

Podobnie jak z Windows Installerem nie ma tu żadnej magii. Ustawienia ClickOnce’a dokonujemy z odpowiedniej karty w VisualStudio.
W przypadku aplikacji XBAP warto pamiętać, iż domyślnie jest uruchamiana w trybie Internet Zone przez co nie mamy dostępu do wielu dobrze znanych i lubianych funkcjonalności.

Podsumowanie

W zasadzie to by było na tyle. Podsumowując miało być 32 lekcje wyszło 20 :). Jednak w niektórych tematach są też omawiane inne, które na liście elementów do egzaminów pojawiają się w innym miejscu, ale ich omówienie w oderwaniu od innych tematów nie ma sensu. Czuję jednak, że jakiś temat jeszcze pominąłem jednak nie mogę w sieci znaleźć listy tematów, które egzamin pokrywa (strony Microsoftu rzucają 404 🙁 ). Tak więc być może powrócę z tematem WPF, ale teraz muszę się zastanowić nad jakimś nowym tematem do cyklu lekcji.
Wszelkie propozycje, uwagi czy też komentarze do tego cyklu mile widziane.

Chyba większośc z nas zetknęło się z wydarzeniem CodeCamp. Jest to konferencja organizowana przez grupę KGD.NET.

Pojawiła się możliwość zorganizowania w tym roku jeszcze jednej konferencji z udziałem światowych gwiazdami naszego .NET-owego podwórka.

Jeśli chciałbyś aby to wydarzenie odbyło się zerknij pod poniższy link i wspomóż organizację CodeCamp w październiku – CodeCamp w październiku

Wczoraj (tj. 10.07.09) na świat wersja 3 Silverlight’a oraz Blenda (jak na razie w wersji RC). Trochę przed tymi wydarzeniami miała miejsce jeszcze jedna premiera o której trochę mniej pisze się. Chodzi mianowicie o kolejna wersja Deep Zoom Composer. Narzędzia do przygotowywania obrazów do funkcjonalności Deep Zoom dostępnej w Silverlight. Postanowiłem trochę podpatrzeć co zawiera najnowsza wersja.
Już pierwszy rzut oka na na ekran komponowania pokazuje zmiany.

Edytor

Po prawej lewej stronie widzimy standardową listę opcji umożliwiających aranżację zdjęć (dostępna była już w poprzedniej wersji). Po prawej jednak jest parę nowości. Wzrok przykuwa rozwijane menu z opcjami (Slideshow, Menu, Internal Links, External Links oraz Impressions. Omówimy je dokładniej w późniejszej części. Dodatkowo mamy jeszcze widok warstw oraz podstawowe informacje o zdjęciu – ścieżka, rozdzielczość, pole na tagi określające zdjęcie oraz coś nowego limity widoczności oraz tooltip.
Dodatkowo mamy możliwość dodania elementu Area. Umożliwia on zaznaczenia wybranego fragmentu obrazka do menu lub pokazu slajdów i następnie umożliwia przejście do wybranego fragmentu.

Pokaz slajdów

W tej wersji mamy możliwość stworzenia pokazu slajdów.

Dodając zdjęcia do specjalnej kolekcji i ustalając ich kolejność w prosty sposób wytworzymy animację z płynnymi przejściami pomiędzy nimi. Przydatne gdy chcemy pokazać. Przydałoby się jednak trochę więcej kontroli nad animacją (np. czas wyświetlania zdjęcia, czas przejścia itp.).

Menu

Kolejną nowością jest menu. Mamy możliwość dodania nawigacji do naszej sceny. Obrazki (i obszary) można dodać do listy z której następnie możemy wybrać interesujący nasz obrazek lub fragment. Przydatne jeśli nie chcemy szukać na scenie – możemy wybrać go z listy i od razu przejść do interesującego nas fragmentu.

Linki

Każdemu elementowi na naszej scenie możemy przypisać link. Linki mogą być zarówno zewnętrzne jak i wewnętrzne. Te pierwsze mogą prowadzić do dowolnego adresu URL, te drugie przekierowywać do innego elementu na scenie.

Śledzenie

Najnowsza wersja zawiera jeszcze jedną bardzo pożyteczną funkcjonalność. Umożliwia dodanie śledzenia częstotliwości wyświetlania danego obrazka. Opiera się ona na linkach. Definiujemy adres strony, które ma zostać wywołany (np. adres strony, która posiada zainstalowany skrypt Google Analitics).

Podsumowanie

Najnowsza wersja Deep Zoom Composera zawiera kilka przydanych nowości. Szczególnie śledzenie odwiedzin będzie przydatne do zastosowań bardziej komercyjnych (można badać, która cześć naszej sceny jest najczęściej odwiedzana).
Z negatywnych rzeczy można tylko wymienić, iż czasami przy eksporcie operacja zakańcza się bez żadnej informacji o błędzie, jednak kompozycja nie jest poprawnie przygotowana i nie można jej otworzyć.

Projekt

Pełny projekt do zobaczenia poniżej:

Do zobaczenia za mniej więcej tydzień. Na najbliższe dni ruszam troszkę bardziej na północ:

Wyświetl większą mapę

W poprzednim odcinku pokazaliśmy sobie jak możemy stworzyć animacje w WPFie za pomocą C#. Dziś zobaczymy jak można to zrobić przy użyciu deklaratywnego języka XAML.

EventTrigger i Storyboard

Przy okazji omawiania triggerów, wspomniałem o EventTriggerach i ich zastosowaniu do animacji. Zobaczmy mały przykład jak zdefiniujemy dany trigger oraz Stroyboard.

<Button Content=”Przycisk” x:Name=”przycisk” Width=”200″>

    <Button.Triggers>

        <EventTrigger RoutedEvent=”Button.Click”>

            <EventTrigger.Actions>

                <BeginStoryboard>

                    <Storyboard>

                        <DoubleAnimation To=”50″ Storyboard.TargetProperty=”Width” />

                    Storyboard>

                BeginStoryboard>

            EventTrigger.Actions>

        EventTrigger>

    Button.Triggers>

Button>

Omówmy poszczególne elementy krok po kroku:

Zaczynamy od zdefiniowania elementu EventTrigger i ustawienia jego właściwości RoutedEvent. Jego wartość ustawimy na Button.Click, zatem interesować nas będzie zdarzenia naciśnięcia przycisku. Następnie zdefiniujemy akcję, która się wykona, gdy nasze zdarzenie zajdzie. Robimy to w tagach EventTriggers.Actions. Zaczynamy od tagu BeginStoryboard a następnie definiujemy Storyboard. Storyboard zawiera animacje, zdefiniowane za pomocą klas XXXAnimation, które będą wykonywać się po zajściu zdarzenia.

Można by się zastanawiać, po co wprowadzać dodatkowo tag BeginStoryboard. Ma to swoje uzasadnienie. Animacją można rozpoczynać także odegranie dźwięku/filmu. Jeśli będziemy chcieli zatrzymać posłużymy się tagiem StopAnimation (przykład był przy omawianiu Multimediów). Stąd taka redundancja w tagach definiujących animację.

Do samej już animacji użyjemy klasy DoubleAnimation definiując jaką właściwość będziemy animować (Width) oraz końcową jej wartość(50).

Oczywiście tak samo jak w C# mamy dostępne właściwości za pomocą możemy kontrolować naszą animację. Dla przykładu ustawmy sobie AutoReverse oraz BeginTime.

<DoubleAnimation To=”50″ Storyboard.TargetProperty=”Width”

                AutoReverse=”True” BeginTime=”0:0:1″/>

Rodzaje animacji

Dotychczas w przykładach posługiwaliśmy się klasą DoubleAnimation jednak jest sporo innych klas na potrzeby animacji prócz tej. Kilka przykładów:

  • In32Animation

  • ColorAnimation

  • PointAnimation

Dodatkowo są także dostępne animacje, które używają “klatek”.

  • In32AnimationUsingKeyFrames

  • ColorAnimationUsingKeyFrames

  • PointAnimationUsingKeyFrames

  • StringAnimationUsingKeyFrames

Pokażmy jak możemy użyć tej ostatniej:

<StackPanel>

    <TextBlock Text=”” x:Name=”crawl” FontSize=”22″ HorizontalAlignment=”Center”/>

    <Button Content=”Przycisk” x:Name=”przycisk” Width=”200″>

        <Button.Triggers>

            <EventTrigger RoutedEvent=”Button.Click”>

                <EventTrigger.Actions>

                    <BeginStoryboard>

                        <Storyboard>

                            <StringAnimationUsingKeyFrames Storyboard.TargetProperty=”Text” Storyboard.TargetName=”crawl”>

                                <DiscreteStringKeyFrame Value=”A long time ago” KeyTime=”0:0:0″ />

                                <DiscreteStringKeyFrame Value=”in a galaxy far, far away…” KeyTime=”0:0:3″ />

                                <DiscreteStringKeyFrame Value=”StarWars” KeyTime=”0:0:7″ />

                                <DiscreteStringKeyFrame Value=”” KeyTime=”0:0:11″ />

                            StringAnimationUsingKeyFrames>

                            <DoubleAnimation Storyboard.TargetProperty=”FontSize” To=”60″

                                            Storyboard.TargetName=”crawl” BeginTime=”0:0:7″ Duration=”0:0:2″ />

                        Storyboard>

                    BeginStoryboard>

                EventTrigger.Actions>

            EventTrigger>

        Button.Triggers>

    Button>

StackPanel>

Poszczególne klatki animacji definiujemy jako DiscreteStringKeyFrame podając jej wartość i czas kiedy ma się dana klatka pojawić. Po uruchomieniu, tekst w kontrolce będzie zmieniał się z godnie z definicją a dodatkowo przy ostatniej klatce zwiększy się rozmiar czcionki, użytej do wyświetlenia napisu do rozmiaru 60.

Na dziś tyle, choć na pewno temat nie jest wyczerpany. W następnym odcinku będzie jeszcze trochę o animacjach przy użyciu klatek. Jednak już teraz warto pobawić się animacjami, gdyż jest to coś czego wcześniej developerzy WinForms nie mieli w swoim warsztacie. Warto spędzić trochę czasu na zapoznanie się z tym.

Dziś o animacjach. Chyba jednej z ciekawszych i rozbudowanej nowości, która pojawiła się w WPF’ie. Dzięki animacjom, nawet zieloni w tym temacie developerzy mogą stworzyć poruszające się interface’y. Animacje tworzy się w dosyć intuicyjny sposób, ale po kolei.

Pierwsza animacja

Zacznijmy od pokazania sobie jak możemy napisać animację w kodzie C#. Niech nasz XAML przyjmie postać taką:

<Button Content=”Przycisk” x:Name=”przycisk” />

a w code-behind napiszmy sobie:

DoubleAnimation anim = new DoubleAnimation();

anim.From = 50;

anim.To = 150;

 

przycisk.BeginAnimation(WidthProperty, anim);

I tyle. Nasza animacja jest gotowa. Po uruchomieniu zobaczmy jak szerokość naszego przycisku się zmienia. Siła animacji, tkwi w tym, że animacja ta nie jest związana z przyciskiem. Jest od niego niezależna. Wystarczy zmienić ostatnią linijkę naszego kodu na:

BeginAnimation(WidthProperty, anim);

i szerokość będzie się zmieniać dla naszego okna!!

Kontrola

Animacje w WPF dają nam duże pole do manewru. W poprzednim przykładzie użyliśmy właściwości To oraz From, które definiują wartości graniczne. Co jeszcze możemy ustawić?

  • Duration – pozwala ustawić jak długo nasza animacja ma się wykonywać.

  • BeginTime – pozwala ustawić opóźnienie lub przyśpieszenie (czasu ujemny) wykonywania animacji.

  • SpeedRatio – szybkość wykonywania animacji. Wartość (0-1> spowalnia ją, >1 przyśpiesza.

  • AutoReverse – ustawienie tej właściwości spowoduje, że po zakończeniu nasza animacja “odtworzy się” w odwrotną stronę.

  • RepeatBehavior – właściwość ta określa ile razy nasza animacja będzie uruchomiona. Przy jej użyciu możemy sprawić, że nasza animacja wykona się odpowiednią liczbę razy; wykona się do przez jakiś zadany czas (nawet, gdy jest on krótszy niż całkowita długość animacji; wykonanie naszej animacji w nieskończoność – RepeatBehaviour.Forever

  • AccelerationRation oraz DecelerationRation – określają jaki procent czasu animacji ma ona odpowiednio przyśpieszać lub zwalniać. Ustawienie właściwości AccelerationRatio na 0.2 spowoduje, że 1/5 czasu naszej animacji prędkość jej odtwarzania będzie się zwiększać a następnie będzie miała stałą wartość.

  • FillBehavior – określa co stanie się z animowaną właściwością po zakończeniu animacji. Możemy wybrać pomiędzy: Stop – przywróci wartość sprzed animacji, lub HoldEnd – wartość będzie taka jak po zakończeniu animacji.

  • IsAdditive – powoduje, dodanie wartość ‘po animacyjnej’ do właściwości From,To. Pomocne, jeśli będziemy kontynuować animację w późniejszym czasie i chcemy rozpocząć, od miejsca gdzie skończyliśmy poprzednio.

  • IsCumulative – działa wraz z właściwością RepeatBehavior. W przypadku np. 4 powtórzeń animacji od 50 do 100, przy ustawionej tej właściwości na true, animacja będzie zmieniać się w zakresie 50-250.

W następnym odcinku pokażemy sobie jak możemy stworzyć animacje w XAMLu.

Jeśli jesteś bywalcem strony http://dotnetomaniak.pl od jakiegoś czasu, to zapewne zauważyłeś, że niedawno zmieniły się kategorie na stronie. Aktualnie mamy następujące:

  • Windows

  • ASP.NET

  • Silverlight

  • Bazy danych i XML

  • Programowanie rozproszone

  • Mobile development

  • Office

  • Architektura

  • Narzędzia

  • Inne

Podział taki mam nadzieję ułatwi klasyfikację dodawanych artykułów, co czasem sprawiało trudności w poprzednim układzie (czy podcast o Agile powinien być w Agile czy w podcastach?).
Martwię się trochę kategorią Inne ale mam nadzieję, że nie będziecie wrzucać tam wszystkiego co popadnie :).

Zastanawiam się nad zrobieniem kilku prawdziwych przedmiotów z logo http://dotnetomaniak.pl – wydaje mi się, że kubki termiczne cieszyłyby się zainteresowaniem. Ktoś się pisze? Są dostępne koszulki, ale nie cieszą się zainteresowaniem :). A może jeszcze coś innego?

Masz jakieś uwagi? A może masz pomysł na usprawnienie strony, przyciągnięcie większej rzeczy programistów .NET lub coś Ci się nie podoba? Napisz mi maila lub umieść swoje uwagi w komentarzu.

Kolejna książka, za której czytanie się zabrałem. Kolejna o technologii Silverlight. Już jakiś czas temu ją przeczytałem, ale jakoś nie mogłem zebrać się na napisanie podsumowania.

Spróbujmy zatem ją podsumować. Muszę przyznać, że mam mieszane uczucia. Książka nie jest zła. Dużo (ciekawych) przykładów i dużo kodu sprawia, że jest to dobra pozycja techniczna. Co mnie troszkę nużyło to sposób w jaki jest ona napisana. Większość stanowią kursy krok po kroku w punktach napisane co robić, aby osiągnąć dany efekt. Nie jest to złe, ale czytając podobny schemat po raz n-ty, człowiek pomału ma już dosyć. Dodatkowo czasem wyjaśnienia są pisane jak dla kogoś, kto nigdy kodu na oczy nie widział co czasem także frustruje, gdy czyja się jak np. dodać referencję do projektu.

Jakie przykłady są w książce? Poczynając od prostych przykładów z trygonometrią, poprzez symulowanie 3D, kolizje a kończąc na kinematyce i kinematyce odwrotnej. Na zakończenie pokazany jest system cząsteczkowy.

Podsumowując, jeśli ktoś szuka przykładów jak powyższe rzeczy można rozwiązać za pomocą Silverlighta (mnie osobiście, szczególnie przypadł do gustu rozdział o kinematyce i IK) to na pewno z tej książki dowie się o tym. Jeśli da radę przetrzymać przy nudnawy czasem styl pisania i banalne czasem wyjaśnienia co i jak robić może śmiało nabyć tę pozycję.

WPF wprowadza do UI pojęcie triggerów, za ich pomocą możemy zmieniać UI w zależności od zajścia jakiegoś zdarzenia. Pozwalają one dodać trochę interakcji do naszej aplikacji. Przyjrzyjmy się im zatem.

Rodzaje

WPF dostarcza nam 3 rodzaje triggerów:

  • property trigger – wywoływany gdy następuje zmiana wartości właściwości zależnej (dependency property)

  • data trigger – wywoływany, gdy następuje zmiana wartości właściwości prostej

  • event trigger – wołany, gdy zaszło określone zdarzenie

Zacznijmy po kolei.

Property trigger

Umożliwia zaczepienie się na dowolną dependency property. Po wystąpieniu zdarzenia następuje określona przez nas zmiana. Gdy warunek nie jest już spełniony, WPF automatycznie przywraca wartość sprzed zmiany. Dlatego wystarczy obsłużyć tylko przypadek, gdy zdarzenie zachodzi. Dla przykładu:

<Style TargetType=”{x:Type Button}”>

    <Style.Triggers>

        <Trigger Property=”IsMouseOver” Value=”True”>

            <Setter Property=”Width” Value=”160″ />

        Trigger>

    Style.Triggers>

Style>

Sprawi, że po najechaniu kursorem na dany przycisk jego szerokość zostanie ustawiona na 160. Po tym jak kursor opuści już dany przycisk, jego szerokość zostanie przywrócona do wartości sprzed zajścia zdarzenia.

Data triggers

Jeśli mamy potrzebę użyć prostych właściwości jako wyzwalacza możemy to zrobić za pomocą DataTrigger.

Wprowadźmy poniższy kod jako nasz trigger:

<DataTrigger Binding=”{Binding ElementName=txtBox, Path=Text}” Value=”secretpassword”>

    <Setter Property=”LayoutTransform”>

        <Setter.Value>

            <ScaleTransform ScaleY=”-1″ CenterX=”.5″/>

        Setter.Value>

    Setter>

DataTrigger>

Co w nim robimy? Wiążemy fakt uruchomienia triggera z występowaniem określonej wartości (secretpassword) w polu tekstowym. Gdy nasz warunek zajdzie, odwracamy w pionie nasze przyciski. Efekt?

Event trigger

Na chwilę obecną opuścimy to zagadnienie. Powrócimy do niego przy okazji omawiania animacji.

Zaawansowane warunki

Oczywiście WPF umożliwia reagowanie także na bardziej złożone warunki, niż tylko pojedyncze zdarzenie. Aby uzyskać warunek LUB wystarczy po prostu dać ten sam efekt, dla dwóch lub więcej zdarzeń. Aby uzyskać warunek I należy posłużyć się klasą MultiTrigger badź MultiDataTrigger.

<MultiTrigger>

    <MultiTrigger.Conditions>

        <Condition Property=”IsMouseOver” Value=”True” />

        <Condition Property=”IsFocused” Value=”True” />

    MultiTrigger.Conditions>

    <Setter Property=”FontSize” Value=”34″/>

MultiTrigger>

UI zostanie zmieniony tylko i wyłącznie gdy przycisk będzie miał focus, oraz kursor myszki będzie się nad nim znajdował.

Na dziś tyle. Następnym razem będzie o animacjach.

Dodatek do ostatniego odcinka kursu o WPF. Przygotowałem wideo, w którym opowiadam mniej więcej to samo o czym była poprzednia lekcja.

Jest tam trochę pomyłek w doborze słownictwa, ale pracuję nad tym.
Miłego oglądania i jeśli ktoś ma to proszę słać uwagi i/lub komentarze.