티스토리 뷰

반응형

1. Trigger Overview

Trigger는 컨트롤의 시각적 효과를 변경하는 데 도움이 되는 WPF의 매우 중요한 기능입니다. 트리거를 이용해서 속성 변경, 데이터 변경, 이벤트 발생 시점에 컨트롤의 시각적 효과를 변경하기 위해 사용되며, Code behind나 ViewModel에서 시각적 효과를 변경하기 위한 동작을 최소화 할 수 있습니다. 물론 Xaml의 코딩량이 그 만큼 늘어나지만, UI와 비지니스 로직의 분리라는 측면에서 보면 매우 좋은 기능입니다.

2. Trigger 종류 및 사용법

종류

  • Property Trigger(Trigger)
    • WPF의 기본 트리거이며 <Trigger/>로 사용할 수 있습니다.
    • Trigger를 소유한 컨트롤의 속성 값이 변경될 때 동작합니다. 다른 컨트롤의 속성값을 사용할 수 없습니다.
    • 의존속성(DependencyProperty)만 사용이 가능합니다.
    • Binding을 사용할 수 없습니다.
    • 여러개의 조건을 사용하기 위해서는 <MultiTrigger/>를 이용합니다.
  • Data Trigger
    • <DataTrigger/>로 사용할 수 있습니다.
    • Binding 기능을 이용하여 데이터와 연결할 수 있으며, 그 데이터가 변경되면 동작합니다.
    • 의존속성(DependencyProperty)과 일반 속성(Public Property)를 모두 사용할 수 있습니다.
    • 접근 가능 범위내 다른 컨트롤의 속성을 사용할 수 있습니다.
    • 여러개의 조건을 사용하기 위해서는 <MultiDataTrigger/>를 이용합니다.
  • Event Trigger
    • <EventTrigger/>로 사용할 수 있습니다.
    • Trigger를 소유한 컨트롤의 이벤트가 발생될 때 동작합니다.
    • 트리거 발생시 Storyboard를 이용해서 프로퍼티 값을 수정하기 때문에 코드가 길어지고, 사용이 불편합니다. 이 경우에는 아래 Microsoft.Xaml.Behaviors.Wpf의 Trigger 사용하는 것을 권장합니다.
  • Microsoft.Xaml.Behaviors.Wpf의 Trigger 사용

사용

  • Style 내부에서 사용
    • 가장 일반적인 사용법
    • <Style.Triggers></Style.Triggers> 내부에서 사용합니다.
    • 각 컨트롤마다 Style Trigger를 지정하거나, Resources에 정의해서 사용합니다.
  • DataTemplate에서 사용 (ItemTemplate 등에 사용됩니다.)
    • <DataTemplate.Triggers></DataTemplate.Triggers> 내부에 사용합니다.
    • DataTemplate 제일 하단부에 추가할 수 있으며, DataTemplate 내부의 각 컨트롤들을 제어할 수 있는 코드를 작성할 수 있습니다.
  • ContentTemplate에서 사용 (Content 프로퍼티 내부에 템플릿을 지정하는데 사용됩니다.)
    • <ContentTemplate.Triggers></ContentTemplate.Triggers> 내부에 사용합니다.
    • ContentTemplate 제일 하단부에 추가할 수 있으며, ContentTemplate 내부의 각 컨트롤들을 제어할 수 있는 코드를 작성할 수 있습니다.
  • ControlTemplate에서 사용하기 (Control의 UI 구성을 변경하기위해 사용합니다.)
    • <ControlTemplate.Triggers></ControlTemplate.Triggers> 내부에 사용합니다.
    • ControlTemplate 제일 하단부에 추가할 수 있으며, ControlTemplate 내부의 각 컨트롤들을 제어할 수 있는 코드를 작성할 수 있습니다.

3. ListBox에서 선택된 아이템 스타일 변경

ListBox에서 데이터를 표시할 때 각 각의 Item들은 ListBoxItem이라는 Control이 만들어지면서, 데이터가 표시 됩니다.

데이터가 표시되는 컨트롤을 통칭해서 ItemContainer라 하고, ListBox의 ListBoxItem의 스타일을 입력하기 위해서는 <ListBox.ItemContainerStyle/>을  이용합니다.

3rd party 컨트롤 중 일부는 전혀 다른 이름의 프로퍼티를 이용해야지 Item의 Style을 변경 할 수 있습니다.

처음으로 사용해볼 트리거는 <Trigger/>입니다.

  • Grid를 2개의 컬럼으로 나누고, 첫번째 컬럼에 ListBox에 ListBox.ItemContainerStyle을 이용해서 Style을 추가 합니다.
  • Style의 TargetType을 반드시 지정해야 합니다.
  • 첫번째 Setter는 HorizontalContentAlignment라는 속성의 값을 Stretch로 변경합니다. 기본 값은 Left입니다.
  • Trigger를 사용해서 ListBoxItem의 IsSelected라는 속성의 값이 True이면, 아래있는 Setter 2개를 실행하게 됩니다.
  • 해당 조건에 만족하는 Item에 대해서만 수행하고, 다른 Item을 선택하면 이전 아이템의 스타일은 원래 상태로 변경됩니다.
ListBoxItem의 Background 컬러는 컨트롤 내부에 기본 트리거로 인해 이 방법으로는 변경할 수 없습니다. 나중에 이 부분에 대해서 설명 드리겠습니다.
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ListBox DisplayMemberPath="Name" ItemsSource="{Binding People}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontSize" Value="15" />
                            <Setter Property="BorderThickness" Value="3" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
        <ListBox
            Grid.Column="1"
            DisplayMemberPath="Name"
            ItemsSource="{Binding People}" />
    </Grid>

실행

아이템 선택

4. ItemTemplate를 이용해서 추가 효과 주기

위에서 다루었던 내용은 ListBoxItem이라는 컨트롤의 Style을 변경하는 것이였는데, 내부 컨텐츠를 좀더 다양하게 변화 시키기 위해서는 직접 ItemTemplate를 만들고 효과를 추가하는 것이 더 좋습니다.

 

Window.Resources에 DataTemplate를 하나 추가 합니다.

 

  • TextBlock의 스타일을 변경하기 위한 트리거는 ListBoxItem의 IsSelected 프로퍼티이기 때문에 해당 프로퍼티를 감시하려면, DataTrigger와 Binding을 이용해야 합니다.
  • Binding에는 RelativeSource를 사용하면 됩니다.
  • 트리거가 발동되면, TextBlock의 2개의 속성 값을 변경합니다.
<DataTemplate x:Key="ListBoxItemTemplate2">
    <TextBlock x:Name="NameTextBlock2" Text="{Binding Name}">
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsSelected, 
                                            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
                                 Value="True">
                        <Setter Property="TextAlignment" Value="Right" />
                        <Setter Property="Foreground" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</DataTemplate>

Binding이 어려운 분들을 위한 팁

Xaml에서 커서를 DataTrigger로 이동합니다.

오른쪽 프로퍼티 창에 Binding 이란 속성 오른쪽 끝에 원통 아이콘을 클릭합니다.

데이터 바인딩을 쉽게 만들어주는 창이 출력됩니다. 

이 창을 이용해서 바인딩을 만들면 훨씬 빠르고 쉽게 만들 수 있습니다.

 

창 이미지와 아래 내용이 서로 연결되는 것을 알 수 있습니다.

Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"

옛날에 저도 이 방법으로 대부분 바인딩 만들어서 사용했습니다. ㅎㅎㅎㅎ

DisplayMemberPath를 지우고, ItemTemplate를 연결합니다.

<ListBox ItemTemplate="{StaticResource ListBoxItemTemplate2}" ItemsSource="{Binding People}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="FontSize" Value="15" />
                    <Setter Property="BorderThickness" Value="3" />
                    <Setter Property="Background" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

실행

5. 소스

WpfTest/TriggerSample1 at master · kaki104/WpfTest (github.com)

 

GitHub - kaki104/WpfTest

Contribute to kaki104/WpfTest development by creating an account on GitHub.

github.com

 

반응형
댓글