четверг, 21 мая 2009 г.

Триггеры в WPF

Триггер(англ. trigger), спусковое устройство (спусковая схема), которое может сколь угодно долго находиться в одном из двух (реже многих) состояний устойчивого равновесия и скачкообразно переключаться из одного состояния в другое под действием внешнего сигнала. (Большая советская энциклопедия).

Собственнов в этом определении сказано все, что нужно для понимания идеи триггеров.
Есть состояние -> происходит событие -> состояние меняется.
Посмотрим простенький пример:

  1. <Style TargetType="{x:Type TextBox}">
  2.       <Setter Property="TextBox.Background">
  3.         <Setter.Value>
  4.           <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
  5.             <GradientStop Offset="0.0" Color="LightCyan" />
  6.             <GradientStop Offset="0.14" Color="Cyan" />
  7.             <GradientStop Offset="0.7" Color="DarkCyan" />
  8.           </LinearGradientBrush>
  9.         </Setter.Value>
  10.       </Setter>
  11.       <Style.Triggers>
  12.         <Trigger Property="IsFocused" Value="True">
  13.           <Setter Property="TextBox.Background">
  14.             <Setter.Value>
  15.               <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
  16.                 <GradientStop Offset="0.0" Color="LightSeaGreen" />
  17.                 <GradientStop Offset="0.14" Color="SeaGreen" />
  18.                 <GradientStop Offset="0.7" Color="DarkSeaGreen" />
  19.               </LinearGradientBrush>
  20.             </Setter.Value>
  21.           </Setter>
  22.         </Trigger>
  23.       </Style.Triggers>
  24.     </Style>
* This source code was highlighted with Source Code Highlighter.


Итак, в первой строке задается картинка, для которой во второй строке мы открываем задание набора тригеров. Тригеры у нас заданы в строках 3 и 11. Превый привязан к событию захода мышки в компонент, второй к покиданию мышкой компонента.
В связи с тем, что свойство Width компонента Image имеет тип double мы и применяем в строках 6 и 14 DoubleAnimation. Задав целевое свойство (Storyboard.TargetProperty), продолжительность анимации (Duration) и к какому значению надо привести (To). В результете при навидении мышки на картинку она будет увеличиваться в размере.
Т.к. для каждой картинки в приложении особенно этого не наделаешься, то само собой можно применить стиль...
Например, вот такой:

  1. <Style TargetType="{x:Type Image}">
  2.       <Setter Property="Image.Width" Value="100"></Setter>
  3.       <Style.Triggers>
  4.         <EventTrigger RoutedEvent="Image.MouseEnter">
  5.           <BeginStoryboard>
  6.             <Storyboard >
  7.               <DoubleAnimation Storyboard.TargetProperty="Width" BeginTime="00:00:00" Duration="00:00:01"   From="100" To="200">
  8.               </DoubleAnimation>
  9.             </Storyboard>
  10.           </BeginStoryboard>
  11.         </EventTrigger>
  12.         <EventTrigger RoutedEvent="Image.MouseLeave">
  13.           <BeginStoryboard>
  14.             <Storyboard >
  15.               <DoubleAnimation Storyboard.TargetProperty="Width" BeginTime="00:00:00" Duration="00:00:01"    To="100">
  16.               </DoubleAnimation>
  17.             </Storyboard>
  18.           </BeginStoryboard>
  19.         </EventTrigger>
  20.       </Style.Triggers>
  21.     </Style>
* This source code was highlighted with Source Code Highlighter.


Теперь все картинки не имеющие переопределений стиля по умолчании будут иметь ширину 100, при наведнии мышки уширяться ;), а при покидании сжиматься...
Не претендуя на изыски можно, например, вот так организовать галлерею:

  1. <StackPanel Orientation="Horizontal">
  2.       <Image Source="Chrysanthemum.jpg"></Image>
  3.       <Image Source="Desert.jpg"></Image>
  4.       <Image Source="Hydrangeas.jpg"></Image>
  5.       <Image Source="Jellyfish.jpg"></Image>
  6.       <Image Source="Koala.jpg"></Image>
  7.       <Image Source="Lighthouse.jpg"></Image>
  8.       <Image Source="Penguins.jpg"></Image>
  9.       <Image Source="Tulips.jpg"></Image>
  10.     </StackPanel>
* This source code was highlighted with Source Code Highlighter.


Ну а в случае, когда нам анимация изменения не нужна, можно применять "не евентовые" тригеры, которые отслеживают изменение свойтсв:

  1. <Style TargetType="{x:Type TextBox}">
  2.       <Setter Property="TextBox.Background">
  3.         <Setter.Value>
  4.           <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
  5.             <GradientStop Offset="0.0" Color="LightCyan" />
  6.             <GradientStop Offset="0.14" Color="Cyan" />
  7.             <GradientStop Offset="0.7" Color="DarkCyan" />
  8.           </LinearGradientBrush>
  9.         </Setter.Value>
  10.       </Setter>
  11.       <Style.Triggers>
  12.         <Trigger Property="IsFocused" Value="True">
  13.           <Setter Property="TextBox.Background">
  14.             <Setter.Value>
  15.               <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
  16.                 <GradientStop Offset="0.0" Color="LightSeaGreen" />
  17.                 <GradientStop Offset="0.14" Color="SeaGreen" />
  18.                 <GradientStop Offset="0.7" Color="DarkSeaGreen" />
  19.               </LinearGradientBrush>
  20.             </Setter.Value>
  21.           </Setter>
  22.         </Trigger>
  23.       </Style.Triggers>
  24.     </Style>
* This source code was highlighted with Source Code Highlighter.


Интерес представляют строки с 11 по 23. Как видно в строке 12 задается тригер который отслеживает состояние свойства IsFocused и как только оно станет равно True к TextBox-у будут применен новый Setter. Причем в данном случае заботиться об обратной смене значений не необходимости. При возврате свойства IsFocused в false значение Setter-а будет отменено и фон станет таким каким был по умолчанию.

Комментариев нет:

Отправить комментарий