niedziela, lipiec 05, 2009

70-502 (WPF) Przygotowania...nr 19.1 - Animacje w XAML

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 Stroyboard

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.

poniedziałek, czerwiec 22, 2009

70-502 (WPF) Przygotowania...nr 19 - Animacje

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.

wtorek, czerwiec 16, 2009

dotnetomaniak.pl się zmienia...

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.

Foundation Silverlight 2 Animation


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

poniedziałek, czerwiec 15, 2009

70-502 (WPF) Przygotowania...nr 18 - Triggers

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.

sobota, czerwiec 13, 2009

70-502 (WPF) Przygotowania...nr 17 - Style

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.

70-502 (WPF) Przygotowania...nr 17 - Style

Po dłuższej przerwie wracamy do kursu o WPF. Dziś będzie o stylach.

WPF wprowadza nowość w zakresie zmiany wyglądu kontrolek. Wszystkie są stworzone w taki sposób, że logika jest oddzielona od wyglądu. Dzięki temu możemy zmienić wygląd cały czas zachowując funkcjonalność.

Style

Co za pomocą nich możemy uzyskać?
Załóżmy, że chcemy zmienić wygląd przycisków w naszej aplikacji, moglibyśmy zmieniać te same ustawienia dla każdego przycisku oddzielnie, ale za pomocą stylów możemy to zrobić w jednym miejscu i po prostu przypisać nasze ustawienia do każdego przycisku. Zobaczmy na krótki przykład:


<StackPanel.Resources>


    <Style x:Key="przycisk">


        <Setter Property="Button.FontSize" Value="22" />


        <Setter Property="Button.Background" Value="Orange" />


        <Setter Property="Button.Width" Value="60" />


    </Style>


</StackPanel.Resources>


Definiujemy sobie, iż nasze przyciski będą na 60 pixeli szeroie,, tło będzie ustawione na kolor pomarańczowy oraz rozmiar fontu ustawimy na 22.
Jak użyć takich ustawień? Zaaplikujemy je do właściwości Style.


<Button Content="1" Style="{StaticResource przycisk}"/>


<Button Content="2" Style="{StaticResource przycisk}"/>


<Button Content="3" Style="{StaticResource przycisk}"/>


<Button Content="4" Style="{StaticResource przycisk}"/>


<Button Content="5" Style="{StaticResource przycisk}"/>


Jaki da nam to efekt?

Oczywiście możemy też ustawiać bardziej skomplikowane właściwości


<Setter Property="Button.RenderTransform">


    <Setter.Value>


        <SkewTransform CenterX=".5" CenterY=".5" AngleX="-10" AngleY="15" />


    </Setter.Value>


</Setter>


Dodatkowo jeśli chcemy możemy ograniczyć dany styl, tylko no konkretnej klasy. Jeśli nasz styl zapiszemy jako:


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


    <Setter Property="FontSize" Value="22" />


    <Setter Property="Background" Value="Orange" />


    <Setter Property="Width" Value="60" />


    <Setter Property="RenderTransform">


        <Setter.Value>


            <SkewTransform CenterX=".5" CenterY=".5" AngleX="-10" AngleY="15" />


        </Setter.Value>


    </Setter>


</Style>


Wtedy wszystkie przyciski automatycznie przyjmą ten styl. Oczywiście nadal będziemy mogli zmienić wygląd przycisku na poziomie konkretnego obiektu.

O stylach na dziś tyle. Następnym razem będzie o triggerach.

niedziela, czerwiec 07, 2009

Bezpieczeństwo - a jak...


Taki właśnie jak powyżej (oczywiście bez blura), wyglądał komunikat błędu, gdy wpisałem niepoprawny login i hasło w jednym z serwisów. Zastanawiam się czy programista piszący ten serwis ma jakiekolwiek pojęcie co robi i czy wie jak ułatwia sprawę komuś, kto chciałby te informacje wykorzystać. Czasem wydaje mi się, że bezpieczeństwo to temat, któremu nie poświęca się dużo czasu bo i po co. Ja w swoich programach dbam o to, aby bezpieczeństwo było tak samo ważnym elementem jak działająca funkcjonalność.

A jak bezpieczeństwo wygląda w waszych aplikacjach? Czy jest uwzględniane już od początku projektu czy raczej coś co zostawia się na koniec do zaimplementowania przez studenta podczas praktyk wakacyjnych? (z całym szacunkiem dla tych ostatnich).

poniedziałek, czerwiec 01, 2009

.NET 4.0 - Zrównoleglanie pętli

Dostępność równoległej pętli For była już dostępna w CTP. Jednak ze względu, iż była to wirtualna maszyna użycie jej było bardzo ograniczone (bez wirtualizacji VPC ma jeden wątek). Skoro teraz jest już Beta postanowiłem się temu przyjrzeć ponownie.

Parallel

Nowy Framework daje nam do dyspozycji trzy warianty: For,For<> oraz ForEach<>. Użycie? Proste:


Parallel.For(1, 10000, delegate(int i)


                          {


                          });


Warto zwrócić uwagę, że jest to przedział lewostronnie domknięty lub <a,b) jak kto woli. Jeśli chcemy jako 3-ci parametr możemy jeszcze przekazać obiekt klasy ParallelOptions, za pomocą którego możemy ustawić kilka opcji naszego równoległego wykonania.

Wraz z nowym obiektem dostajemy także wsparcie w Visual Studio 2010. Pierwszym z nich to okno Parallel Tasks. Pozwala podejrzeć aktualnie nasze aktualnie uruchomione wątki jak i dokonać kilku operacji na nich (zatrzymanie, wznowienie).

Drugie to ParallelStack - to okno pokaże nam stos wywołań naszych wątków. Zacne. Jak to wygląda na obrazku poniżej.

Zachęcam do zabawy z Parallel. Nie masz pomysłów na algorytm wykorzystujący te możliwości? "Kilka" takich zadań, znajdziesz na ProjectEuler.Net. Problemy matematyczne do rozwiązywania za pomocą komputera (lub głowy - da się da...:)).

Wszystkich fanów matematyki i ciekawych problemów zachęcam do zajrzenia tam no i do zaznajomienia się z nową równoległą pętlą w VS 2010.