Pokazywanie postów oznaczonych etykietą property. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą property. Pokaż wszystkie posty

sobota, 8 września 2012

[HTML|JS|CSS] Compass : Animacje CSS3, Transformacje 2D

CSS3 umożliwia pisanie prostych animacji. Możemy na przykład animować zmianę szerokości kontrolki, zmianę koloru czy położenia. Problemem znowu jest zachowanie takiej animacji przy różnych silnikach przeglądarek. Kolejny raz z pomocą przychodzi Compass, udostępniając Mixiny pozwalające w łatwy sposób tworzyć efekty przejść. Mamy do dyspozycji cztery opcje:
  1. transition-property - które property chcemy animować (domyślnie wszystkie).
  2. transition-duration - czas trwania animacji (domyślnie 0s)
  3. transition-timing-function - funkcja służąca do wyliczenia wartości w kolejnych chwilach czasu (odpowiednik easing function z WPF)
  4. transition-delay - opóźnienie, po jakim wykona się efekt (domyślnie 0s)

Przykładowy sposób użycia, przy zdarzenie hover (najechanie myszą):

.inflated{
 @include transition-property(width);
 @include transition-duration(1s);
 @include transition-timing-function(ease-out);
 @include transition-delay(0.2s);
 width: 100px;
 &:hover{
  width : 200px;
 }
}

Dodatkowo za pomocą mixinów Compassa możemy tworzyć proste transformacje 2D, takie jak:
  • Translacje

.translated{
 &:hover{
  @include translateX(10px);
  @include translateY(200px);
 }
}

  • Rotacje


.rotated{
 &:hover{
  @include rotate(33deg);
 }
}

  • Skalowanie


.scaled{
 @include transition-duration(1s);
 &:hover{
  @include scale(3);  
 }
}

Pełna lista możliwości dostępna jest tutaj.

wtorek, 28 sierpnia 2012

[WPF] Triggers

Triggery stanowią kolejny bardzo użyteczny mechanizm WPF. Pojedynczy Trigger składa się z zestawy setterów, podobnie jak styl, oraz z warunku, jaki musi zostać spełniony, aby te settery zostały zastosowane.Zatem dzięki zastosowaniu triggerów, mamy okazję przenieść sporo kodu dotyczącego wyglądu z code behind do xaml. Wprowadzono trzy rodzaje triggerów :

  • Property Trigger

Warunek wyzwolenia takiego triggera zależy od tego, czy któreś dependency property osiągnęło pewną wartość. W momencie, gdy property ponownie zmieni wartość, zmiany zostaną cofnięte. Przykład :

<Style TargetType="{x:Type Button}">
    <Setter Property="Background" Value="Red" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="BorderThickness" Value="2" />
    <Setter Property="BorderBrush" Value="Blue" />
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Green" />
        </Trigger>
    </Style.Triggers>
</Style>

  • Data Trigger

Działa podobnie jak Property Trigger, ale może być wyzwolony przez dowolne .NETowe property. Przez to obowiązuje nieco trudniejsza składa przy definiowaniu tego Triggera. Przykładowo tworząc w CodeBehind property IsHidden, możemy sterować widocznością TextBlocka.


  public bool IsHidden
        {
            get { return _isHidden; }
            set
            {
                _isHidden = value;
                Debug.WriteLine(value);
                if(PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("IsHidden"));
            }
        }

Teraz można zdefiniować DataTrigger.


<Style TargetType="{x:Type TextBlock}" >
    <Style.Triggers>
        <DataTrigger Value="True"
            Binding="{Binding ElementName=Window,Path=IsHidden}">
            <Setter Property="Visibility" Value="Collapsed" />
        </DataTrigger>
    </Style.Triggers>
</Style>

  • EventTrigger

Głównym ich zastosowaniem jest wyzwalanie animacji zapisanych w storyboardach w momencie, gdy zajdzie jakieś zdarzenie. Mając nagrany w Resources storyboard, możemy się posłużyć następującą składnią:


<Window.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Storyboard="{StaticResource MyStoryboard}"/>
    </EventTrigger>
</Window.Triggers>

Dodatkowo często chcemy stworzyć bardziej złożoną logikę, niż zajście pojedynczego warunku. Mamy do dyspozycji konstrukcje będące ekwiwalentem logicznych funkcji AND i OR.

  • AND

Narzędziem, służącym do zbudowania tej funkcji logicznej jest MultiTrigger.


<Style.Triggers>    
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="IsMouseOver" Value="True" />
            <Condition Property="IsVisible" Value="True" />
        </MultiTrigger.Conditions>
        <MultiTrigger.Setters>
            <Setter Property="Foreground" Value="Black"/>
        </MultiTrigger.Setters>
    </MultiTrigger>
</Style.Triggers>

  • OR

Aby stworzyć funkcję OR, można dodać kilka Triggerów obok siebie z tymi samymi setterami. Taka konstrukcja będzie odpowiadała alternatywie.

czwartek, 16 sierpnia 2012

[WPF] Attached Property

Attached Property to nic innego jak Dependency Property dołączane do obiektów już istniejących. Jest to na przykład świetny sposób na rozszerzanie kontrolek z których nie można dziedziczyć, lub z których dziedziczyć się nie opłaca, bo chcemy dodać tylko jedną prostą funkcjonalność. Przykładem AP jest Grid.Column ustawiane dla elementów potomnych. Ustawia się je w celu poinformowania rodzica o tym, jak mają być ustawione dzieci. Ogólnie założeniem AP jest, by klasy zgromadzone w pewien sposób w hierarchii lub powiązane w pewien logiczny sposób mogły zgłaszać wspólną informację do typu, które definiuje Attached Property. Typ ten może być zdefiniowany, jako rodzic, zawierający wiele dzieci. Iterując po nich może on wyciągać informacje, które go interesują. Inne zastosowanie, to serwis, który jest powiadamiany w momencie, gdy AttachedProperty jest ustawiane.

W poniższym przykładzie stworzono serwis, kontrolujący to, który prostokąt został wybrany. Attached Property rejestrowane jest podobnie jak Dependency Property specjalną metodą RegisterAttached.

<Window x:Class="Attached_Property.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Attached_Property="clr-namespace:Attached_Property" Title="MainWindow" Height="200" Width="200">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Rectangle Width="100" Height="100" MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect1" Stroke="Red" Grid.Column="0" Grid.Row="0" 
                   Fill="LightGreen" Attached_Property:RectangleService.IsChecked="True" />
        <Rectangle Width="100" Height="100"  MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect2" Stroke="Red" Grid.Column="1" Grid.Row="0" />
        <Rectangle Width="100" Height="100" MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect3" Stroke="Red" Grid.Column="0" Grid.Row="1" />
        <Rectangle Width="100" Height="100" MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect4" Stroke="Red" Grid.Column="1" Grid.Row="1" />
    </Grid>
</Window>


 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Rect3_MouseEnter(object sender, MouseEventArgs e)
        {
            RectangleService.SetIsChecked(sender as DependencyObject, true);
        }
    }


 public class RectangleService
    {
        public static readonly DependencyProperty IsCheckedProperty;

        public static Rectangle CheckedRect { get; set; }

        static RectangleService()
        {
            IsCheckedProperty = DependencyProperty.RegisterAttached("IsChecked", 
                              typeof (bool), typeof (Rectangle),
                                                new PropertyMetadata(false));
        }

        public static void SetIsChecked(DependencyObject element, bool value)
        {
            element.SetValue(RectangleService.IsCheckedProperty, value);
            //service logic
            if (!value) return;
            if(CheckedRect != null)
                CheckedRect.Fill = new SolidColorBrush(Colors.Yellow);
            CheckedRect = element as Rectangle;
            if(CheckedRect== null)
                return;
            CheckedRect.Fill = new SolidColorBrush(Colors.LightGreen);
        }

        public static bool GetIsChecked(DependencyObject element)
        {
            return (bool)element.GetValue(RectangleService.IsCheckedProperty);
        }

środa, 15 sierpnia 2012

[WPF] Dependency Property

Jedną z najważniejszych koncepcji w WPF jest Dependency Property. Umożliwiają one stylowanie, automatyczny data binding czy animowanie dowolnych właściwości. Dependency Property może być zmieniane przez wiele obiektów jednocześnie, a jego największą zaletą jest wbudowana zdolność do notyfikowania o zmianach wartości. DP mogą być także zmieniane z poziomu xaml co jest następną ich zaletą. Zatem przy tworzeniu własnych kontrolek jest to bardzo wygodne rozwiązanie. Kolejną korzyścią wynikającą z zastosowania DP jest możliwosć zdefiniowania Property Triggerów - warunkowych akcji wykonywanych, gdy property osiągnie pewną wartość

Od strony języka DP są propertiesami, budowanymi w dość nietypowy sposób. Należy dodać do klasy kontrolki statyczne publiczne pole tylko do odczytu, gdzie nazwa to nazwa property z dodanym "Property". Następnie w statycznym konstruktorze rejestruje się DP za pomocą metody DependencyProperty.Register. Przez parametry tej metody można określić domyślną wartość i metodę wołaną przy zmianie wartości. Można także zdefiniować pewien "wrapper", który będzie opakowywał ustawianie i odczyt wartości DP.

W poniższym przykładzie dla kontrolki tykającego zegarka zdefiniowano Dependency Property Ticks, które reprezentuje liczbę uderzeń zegarka.

 public partial class TickingTimer : UserControl
    {

        public static readonly DependencyProperty TicksProperty;

        public int Ticks
        {
            get { return (int)GetValue(TickingTimer.TicksProperty); }
            set { SetValue(TickingTimer.TicksProperty, value); }
        }

        static TickingTimer()
        {
            TickingTimer.TicksProperty = DependencyProperty.Register("Ticks",
                typeof(int), typeof(TickingTimer),
                new FrameworkPropertyMetadata(0,
                new PropertyChangedCallback(OnTicksChanged)));
        }

        private static void OnTicksChanged(DependencyObject o, DependencyPropertyChangedEventArgs eventArgs)
        {
            Console.Beep();
        }
//LOGIKA KONTROLKI
     }

Kontrolkę taką można dodać do okna i zbindować się do naszego Dependency Property Ticks.

<Window x:Class="Dependency_Property.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:Dependency_Property="clr-namespace:Dependency_Property" 
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Dependency_Property:TickingTimer x:Name="Timer" Ticks="5" />
        <Label Content="{Binding ElementName=Timer,  Path=Ticks}" />
    </Grid>
</Window>