티스토리 뷰

반응형

2023.01.25 - [WPF .NET] - Trigger를 사용해서 동적 UI 구성하기 Part4 - EventTrigger

2022.12.29 - [WPF .NET] - Trigger를 사용해서 동적 UI 구성하기 Part3 - DataTrigger

2022.12.21 - [WPF .NET] - Trigger를 사용해서 동적 UI 구성하기 Part2

2022.12.14 - [WPF .NET] - Trigger를 사용해서 동적 UI 구성하기 Part1 - Overview

 

이전 Trigger를 사용해서 동적 UI 구성하기를 이번에는 Microsoft.Xaml.Behaviors.Wpf를 사용하기로 변경하도록 하겠습니다. 프로젝트명은 TriggerSample5이며, TriggerSample4의 소스를 변경합니다.

WPF로 애플리케이션을 만들기 위해서 꼭 알아야 할 또하나의 Nuget package이며, 유용한 Trigger, Behavior, Action들을 포함하고 있습니다.

1. Microsoft.Xaml.Behaviors.Wpf Nuget package

Xaml Behavior는 WPF 응용 프로그램에 재사용이 가능한 Behavior와 Action을 여러가지 제공하고 있으며, 사용자가 원하는 기능을 구현하는 것도 지원을 하고 있습니다.

2. Nuget package 추가

Microsoft.Xaml.Behaviors.Wpf nuget package를 추가합니다.

3. Animation

  • Control Storyboard Action
    • 스토리보드를 Play, Stop, TogglePlayPause, Pause, Resume, SkipToFill 시킬 수 있습니다.

b라는 Namespace를 추가합니다.

xmlns:b="http://schemas.microsoft.com/xaml/behaviors"

Storyboard1에 AutoReverse 속성을 True, RepeatBehavior를 Forever로 설정합니다.

        <Storyboard
            x:Key="Storyboard1"
            AutoReverse="True"
            RepeatBehavior="Forever">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="textBlock1" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                <EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="2" />
                <EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="1" />
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="textBlock1" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                <EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="2" />
                <EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="1" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>

하단의 Button 클릭 부분을 아래와 같이 수정합니다.

b를 이용하면 간단하게 아래의 방법으로 EventTrigger를 쉽게 사용할 수 있습니다. 이전에는 RoutedEvent="Button.Click"을 이용해야 했지만, 지금은 Click로 사용 가능합니다.

<Button
    Grid.Row="8"
    Grid.ColumnSpan="2"
    Content="PlayStoryboard">
    <b:Interaction.Triggers>
        <b:EventTrigger EventName="Click">
            <b:ControlStoryboardAction ControlStoryboardOption="TogglePlayPause" Storyboard="{StaticResource Storyboard1}" />
        </b:EventTrigger>
    </b:Interaction.Triggers>
</Button>
  • Mouse Drag Element Behavior
    • 구성 요소를 마우스의 드래그 동작으로 이동 할 수 있습니다.

DataGrid 컨트롤을 런타임에 드래그로 위치를 이동 시킬 수 있습니다.

<DataGrid
    Grid.Row="7"
    Grid.Column="1"
    IsReadOnly="True"
    ItemsSource="{Binding SelectedPerson.Childs}">
    <b:Interaction.Behaviors>
        <b:MouseDragElementBehavior />
    </b:Interaction.Behaviors>
</DataGrid>
  • Trazlate Zoom Rotate Behavior
    • 터치 기반 상호 작용을 지원합니다.
    • 터치를 이용해서 이동이나 회전, 확대를 할 수 있습니다.
    • 비터치 장치에서는 Mouse Drag Element Behavior와 비슷한 동작을 수행합니다.
  • Fluid Move Behavior
    • 구성 요소를 부드럽게 이동시키는 비헤이비어

ItemsPanelTamplate를 생성합니다. ItemsPanelTemplate에 밑줄이 그어지면서 오류가 발생하지만, 실행은 가능합니다. 정확한 원인은 모르겠네용. Behavior Sample에는 문제 없었는데;; 자주 사용되는 녀석은 아니니 참고만 하세요

<ItemsPanelTemplate x:Key="ListBoxItemsPanel1">
    <StackPanel>
        <b:Interaction.Behaviors>
            <b:FluidMoveBehavior AppliesTo="Children" Duration="00:00:01">
                <b:FluidMoveBehavior.EaseY>
                    <BounceEase Bounces="2" EasingMode="EaseOut" />
                </b:FluidMoveBehavior.EaseY>
            </b:FluidMoveBehavior>
        </b:Interaction.Behaviors>
    </StackPanel>
</ItemsPanelTemplate>

ListBox의 ItemsPanel을 설정합니다.

Remove 버튼을 하나 추가하고, 버튼을 클릭했을 때 ViewModel에서 People의 0번째 아이템을 삭제합니다.

<ListBox
    Grid.Row="1"
    ItemTemplate="{StaticResource PersonItemTemplate}"
    ItemsPanel="{DynamicResource ListBoxItemsPanel1}"
    ItemsSource="{Binding People}"
    SelectedItem="{Binding SelectedPerson, Mode=TwoWay}" />
  • Fluid Move Set Tag Behavior
    • 다른 항목을 기반으로 FluidMoveBehavior 시작 위치를 설정할 수 있습니다.

ListBox에서 선택한 아이뎀을 보여주는 상세 영역으로 날라가는 애니메이션을 표현합니다.

이동할 대상을 FluidMoveSetTagBehavior로 지정합니다.

<DataTemplate x:Key="PersonItemTemplate">
    <Border x:Name="Bd" Background="Gray">
        <b:Interaction.Behaviors>
            <b:FluidMoveSetTagBehavior Tag="DataContext" />
        </b:Interaction.Behaviors>
        <StackPanel Orientation="Horizontal">
            <TextBlock
                x:Name="Content"
                Margin="4"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                FontSize="12"
                Foreground="White"
                Style="{StaticResource AnimationTextBlockStyle}"
                Text="{Binding Name}"
                TextAlignment="Center" />
        </StackPanel>
    </Border>
    <!-- 중략 -->
</DataTemplate>

이동할 위치를 FluidMoveBehavior로 지정합니다.

이 때 DataContext를 아래와 같이 ListBox의 SelectedItem으로 지정해 주어야 합니다. 즉, 이 Grid의 DataContext는 ViewModel이 아니라 PeopleListBox의 SelectedItem이 됩니다.

<Grid
    x:Name="grid"
    Grid.Column="1"
    Margin="4"
    DataContext="{Binding ElementName=PeopleListBox, Path=SelectedItem}">
    <b:Interaction.Behaviors>
        <b:FluidMoveBehavior InitialTag="DataContext" />
    </b:Interaction.Behaviors>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <!-- 중략 -->
</Grid>

실행 결과는 직접 확인하시면 좋을 것 같습니다. 재미있네요 ㅋㅋ

사용해보니 DataTemplate와 ItemsPanelTemplate 내부에 FluidMoveBehavior나 FluidMoveSetTagBehavior를 사용하니 오류가 나는데, 이 부분이 신경 쓰이신다면, 사용하지 않는 것을 권장합니다. 딱히 중요한 기능은 아니라..

오류가 발생하는 리소스를 ListBox에 연결하기 위해서 StaticResource가 아니라 DynamicResource로 변경했으니 참고 부탁드립니다.

5. 소스

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

 

GitHub - kaki104/WpfTest

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

github.com

 

반응형
댓글