2018년 1월 31일 수요일

[WPF학원/WPF예제] 프로퍼티 트리거(Property Trigger)

(WPF학원/WPF교육/WPF트리거)프로퍼티 트리거(Property Trigger) 

프로퍼티 트리거(Property Trigger)
n  TriggerBase의 자식 클래스중 가장 일반적인 클래스는 특정 프로퍼티의 변화(어떤 값을 가졌을 때)에 내부에 정의한 Setter 컬렉션이 실행되는 트리거 이다.
n  컨트롤이나 엘리먼트가 반응하는 방법을 정의하는 Trigger 인데 대부분 이 프로퍼티는 IsMouseOver 프로퍼티와 같은 사용자의 입력 프로퍼티를 포함하는데 이때 Trigger는 Setter에서 정의된 프로퍼티를 변경한다.
n  아래 예문에서 최초 TextBlock은 전경색(Foreground)을 Gree 색을 가지지만 마우스가 진입되면 Foreground가 빨강, 글씨 아래에 Uderline이 생긴다.
<Grid>
        <TextBlock Name="tblk1" Text="Hello, WPF world!" FontSize="30"
                   HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Setter Property="Foreground" Value="Green"></Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                           <Setter Property="Foreground" Value="Red" />
                           <Setter Property="TextDecorations" Value="Underline" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>

n  실행화면


n  Trigger의 프로퍼티가 Boolean으로 제한되는 것은 아니지만 흔히 사용되고 이 프로퍼티는 반드시 의존프로퍼티에 의해 지원되어야 하다. (IsMouseOver, ISFocused, IsPressed 등)
n  Style과 같이 Triggers는 Setters라는 이름의 프로퍼티를 가지고 있으며 이 프로퍼티 Triggers의 컨텐트 프로퍼티(ContentProperty)로 Trigger는 하나 이상의 Setter 엘리먼트를 포함할 수 있다.
n  다른 예제를 하나 살펴보자. 최초 화면이 로딩될 때 Button 및 TextBlock의 전경색은 빨강, TextBlock의 Text 속성은 “Hello WPF!” 라는 값을 가진다. 두 컨트롤 모두 마우스가 진입을 하면 프로퍼티 트리거가 동작을 하는데 Button은 전경색을 파랑으로 변경하고, TextBlock은 전경색이 파랑으로, Text 속성은 “버튼으로 진입했습니다.”로 변경 된다.

<Window x:Class="WpfApp15.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        Title="MainWindow" Height="200" Width="400">
    <Window.Resources>
        <Style x:Key = "MyStyle">
            <Setter Property = "Control.Foreground" Value = "Red" />
            <Setter Property = "TextBlock.Text" Value = "Hello WPF!" />
            <Style.Triggers>
                <Trigger Property = "Control.IsMouseOver" Value = "True">
                    <Setter Property = "Control.Foreground" Value = "Blue" />
                    <Setter Property="TextBlock.Text" Value="버튼으로 진입했습니다."/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Width = "100" Height = "70"
         Style = "{StaticResource MyStyle}" Content = "Trigger"/>
        <TextBlock Style = "{StaticResource MyStyle}"
                   FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </StackPanel>
</Window>





n  다른 예제를 하나 살펴보자.
n  Trigger 엘리먼트가 같은 프로퍼티를 두번 설정하면 뒤 Trigger 엘리먼트는 이전의 것을 오버라이딩 한다. 이전 예제에서 두 Trigger 프로퍼티의 순서를 바꾸면 전경색은 빨강으로 바뀔 수 없다. IsPressed가 true이면 IsMouseOver 역시 true이기 때문이다. 버튼에 마우스를 누르려면 버튼 안으로 마우스가 진입해야 하므로 항상 IsMouseOver 상태가 된다.
n  IsMouseOver가 true일 경우 텍스트를 파랑으로 표시하라는 것이 IsMouseOver Trigger의 마지막에 재정의 되어 명시되었기 때문에 재정의된 마지막 것이 적용된다.

[MainWindow.xaml]
<Window x:Class="WpfApp6.MainWindow"
        xmlns:local="clr-namespace:WpfApp6"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <Style x:Key="normal">
                <Setter Property="Control.FontSize" Value="24" />
                <Setter Property="Control.HorizontalAlignment" Value="Center" />
                <Setter Property="Control.Margin" Value="24" />
                <EventSetter Event="Button.Click" Handler="ButtonOnClick" />
                <Style.Triggers>
                    <Trigger Property="Control.IsMouseOver" Value="true">
                        <Setter Property="Control.FontStyle" Value="Italic" />
                        <Setter Property="Control.Foreground" Value="Blue" />
                    </Trigger>
                    <Trigger Property="Button.IsPressed" Value="true">
                        <Setter Property="Control.Foreground" Value="Red" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Resources>

        <Button Style="{StaticResource normal}">
            Button Number 1
        </Button>

        <Button Style="{StaticResource normal}">
            Button Number 2
        </Button>

        <Button Style="{StaticResource normal}">
            Button Number 3
        </Button>
    </StackPanel>
</Window>

[MainWinow.xaml.cs]
using System.Windows;
using System.Windows.Controls;
using System.Threading;

namespace WpfApp6
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        void ButtonOnClick(object sender, RoutedEventArgs args)
        {
            Thread.Sleep(1000);
            Button btn = args.Source as Button;
            MessageBox.Show(btn.Content + " has been clicked", Title);
        }
    }
}

n  순서를 정의하기가 어려운 경우 MultiTrigger를 고려하면 되는데 MultiTrigger는 2개나 그이상의 조건이 만족할 때 발생된다는 것을 제외하면 Trigger와 유사하다.


<Window x:Class="WpfApp6.MainWindow"
        xmlns:local="clr-namespace:WpfApp6"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <Style x:Key="normal">
                <Setter Property="Control.FontSize" Value="24" />
                <Setter Property="Control.HorizontalAlignment" Value="Center" />
                <Setter Property="Control.Margin" Value="24" />
                <EventSetter Event="Button.Click" Handler="ButtonOnClick" />

                <Style.Triggers>
                    <Trigger Property="Button.IsPressed" Value="True">
                        <Setter Property="Control.Foreground" Value="Red" />
                    </Trigger>

                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="Control.IsMouseOver" Value="True" />
                            <Condition Property="Button.IsPressed" Value="False" />
                        </MultiTrigger.Conditions>
                        <Setter Property="Control.FontStyle" Value="Italic" />
                        <Setter Property="Control.Foreground" Value="Blue" />
                    </MultiTrigger>

                </Style.Triggers>
            </Style>
        </StackPanel.Resources>

        <Button Style="{StaticResource normal}">
            Button Number 1
        </Button>

        <Button Style="{StaticResource normal}">
            Button Number 2
        </Button>

        <Button Style="{StaticResource normal}">
            Button Number 3
        </Button>
    </StackPanel>
</Window>