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>