PROGRAMMING WORKSHOP

.NetFrameWork | WPF - Style + Triggers



엑셀에도 워드에도 Style개체가 있다
엑셀에서는 별로 모양을 내는 작업이 없으니 사용빈도가 거의 없어서
사용들을 별로 하지 않으나 알고 사용하면 편리하다
특히 다른 프로그램에서는 좀 다르다
사람도 모양을 내는 것은 Styling이라고 하니
Style개체는 중요하다
특히 HTML문서에서나 WPF에서는 핵심개체이다
예를 들어서 여러개의 버튼이 있다
똑같은 모양을 내고 싶은데 버튼마다 일일이 속성을 주고 모양을
내는 작업은 중복되는 일을 많이 하는 셈이다
하나의 Style을 만들어 놓고 여러개의 버튼이 공동으로 같은 Style을
사용한다면 참 편리하지 않겠는가..

새 WPF프로젝트를 만들고 XAML 편집기에서 <Window>.....</Window>
Tag사이에 아래와 같이 입력하여 주면

<Grid> <Grid.Resources> <Style TargetType="Button"> <Setter Property="Width" Value="100" /> <Setter Property="Height" Value="30" /> <Setter Property="Margin" Value="10" /> <Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="Foreground" Value="White" /> <Setter Property="Background" Value="Red" /> <Setter Property="Opacity" Value="1" /> </Style> </Grid.Resources> <StackPanel Orientation="Horizontal"> <Button Content="Button_1" /> <Button Content="Button_2" Opacity="0.5" /> <Button Content="Button_3" /> </StackPanel> </Grid>

위와 같이 하면 하나의 Style개체에 서식을 하면 모든 버튼에
해당 스타일(서식)이 적용되는 것이다
그러니 버튼이 10개가 되던 100개가 되던 일정한 모양의
버튼이 만들어진다
그러나 개중에는 나는 나만의 서식을 하고 싶다고 하면
해당 버튼에서 속성값을 다르게 주면 해당 버튼개체는 해당 속성이
Overriding(덮어쓰기)가 되어 버리니 참으로 자유로운 셈이다
자세한 해설은 화일에 달아 놓았다



또 Style이 엑셀이나 워드와 다른 것은 이곳에 Trigger개체를
사용하여 에니메이션을 모든 버튼에 적용할수 있다는 것이다
예를 들어서 버튼에 마우스를 갖여 가면 폭과 높이가 커지게 하고 싶다
이것을 버튼마다 일일이 해주자면 골 빠진다
이것을 Style개체에 같이 적용해주면 모든 버튼이 공통으로
적용받게 되는 것이다

<style...> ... ... <Style.Triggers> <Trigger Property="IsMouseOver" Value="True" > <Setter Property="Height" Value="100" /> <Setter Property="Width" Value="120" /> </Trigger> </Style.Triggers> </style>

와 같이 Style개체의 Triggers 집합체에
Trigger개체를 만들어 넣는다
속성 IsMouseOver 라는 속성의 값이 True일때
높이는 100으로 하고 폭은 120으로 하라는 XAML 코딩인 것이다

이벤트와는 다른 속성으로 이벤트를 인식하는 셈이다
이값이 변하는 것에 따라서 어떤 작업을 명령하는 셈이다
물론 이벤트로 처리하는 이벤트명은 또 별도로 있다

***[LOG-IN]***

Trigger는 위와 같이 속성 Trigger가 있는가 하면
이벤트프로시져를 일으키는 EventTrigger가 있다
속성값이 바뀌었을때 어떤 일을 하는 것이 아닌, 버튼을 크릭하였거나
하면 즉 Click이벤트때 어떤 일이 벌어지게 하는 것이 있는 것이다

XAML문에서 작성한 Style개체를 VB코드에서 접근하여 옵션버튼의 선택에
따른 버튼의 Click이벤트가 다른 스타일 개체를 구현하게 해보자
페이지 맨위의 버튼에 지금 학습하려는 내용을 실행화일로
연결해 놓았으니 보시고 내용을 살펴보시면 도움이 될 것이다

다양하게 Style개체를 몇개 XAML로 작성한다
이것을 폼이 실행된후 옵션버튼을 크릭할때마다 특정한 Style개체를
버튼의 크릭이벤트가 실행될때 구현되게 연결해준다..
버튼을 크릭한다!!!
다양한 행동을 하게 되는 것을 볼수 있다

핵심은 Style개체에 Trigger개체를 포함시켜서 다양한 이벤트에서의
행동을 다양하게 구현할수 있다는 것!!

<Style TargetType="{x:Type Button}" x:Key="StyleBase" >
   <Setter Property="BorderBrush" Value="Black" />
   <Setter Property="FontSize" Value="16" />
   <Setter Property="FontWeight" Value="Heavy" />
   <Setter Property="Foreground" Value="Red" />
</Style>

위의 Style개체는 Button의 경우 모두 이 Style개체를 적용하게 되는 것이다
그런데 여러개의 버튼이 있을때
기본적으로 버튼의 Style은 모두 같은데 몇개의 속성값만 다르다면
좀더 다른 방법을 사용하여야 할 것이다
위의 Style개체는 기본적으로 적용하는 Common한 속성들이고
각버튼마다 다른 특징을 주고 싶은 것이다

<Style TargetType="{x:Type Button}" x:Key="Style_1" BasedOn="{StaticResource StyleBase}" >
   <Setter Property="RenderTransform" >
      <Setter.Value >
         <TranslateTransform />
      </Setter.Value>
   </Setter>
   <Style.Triggers>
      <EventTrigger RoutedEvent="Button.Click">
         <BeginStoryboard>
         <Storyboard>
            <DoubleAnimation
            Storyboard.TargetProperty="(Button.RenderTransform).(TranslateTransform.Y)"
            From="10" To="200" Duration="0:0:05"
            AutoReverse="True" />
         </Storyboard>
         </BeginStoryboard>
      </EventTrigger>
   </Style.Triggers>
</Style>

두번째 Style개체에서 첫번째 Style개체내용을 그대로 상속받도록 하면
편리한 것이다
그래서 그런 상속의 표현을 BasedOn이라는 속성으로 표현하고
값은 첫째 Style개체의 키값을 읽어 들이면 두번째 Style개체는 첫번째 Style개체의
내용을 같이 표현하게 되는 것이다

중복은 나쁜 것이다!!라는 것을 표현한 셈이다
한번 사용한 것을 다른 곳에서도 재사용하게 하는 것

두번째 Style에서는 어떤 특징을 주었냐 하면
Triggers라는 Trigger개체의 집합체속에..
EventTrigger라는 개체를 만들어 넣은 것이다
맨 위에 표현한 Trigger개체는 그냥 속성값의 변화가 있을 때이고
이 것은 EventTrigger개체..즉 어떤 지정된 이벤트에서 처리한다는 것이다
즉 두번째 Style개체를 적용하는 버튼은 이 EventTrigger개체의 능력을
포함하게 되는 셈이다

XAML은 Design Time에 개체들을 만드는 것이고
VB는 Run Time에 개체들을 만들수 있다(위의 내용들은 모두 VB에서
프로그래밍적으로 처리할수 있는 것)
하지만 XAML문의 기본은 알고 있고, 필요에 따라서는 Disign Time+Run Time의 적절한
조화를 즐겨가면서 프로그래밍을 하면 되는 것이다

이벤트Trigger개체는 하나의 속성을 갖고 있다..RoutedEvent
즉 값으로 Event명을 주면 된다..여기에서는 버튼의 Click이벤트...그래서

<EventTrigger RoutedEvent="Button.Click" >

이제 버튼을 크릭하면 어떤 것이 실행되느냐 하면
BeginStoryBoard 라는 개체가 실행된다..즉 그 하위개체인 StoryBoard를
시작하라는 일을한다

StoryBoard개체는 다양한 에니메이션 개체를 지휘하는 개체..
여기에서는 DoubleAnimation 개체를 실행하게 되는 것이다
DoubleAnmation은 Button개체의 RenderTransform속성의 하위 속성
TranslateTransform 속성의 최종 속성 X값 혹은 Y값..
여기에서 XAML의 특징적인 것을 이해하여야 한다
Win32시스템의 Window나 VBA의 UserForm의 개체들의 속성은
그냥 1대1 ..속성=Value로 끝났다..
그런데 XAML개체들은 하나의 속성이 하나의 값을 갖고 있지 않고 다양한
값을 갖고 있을수 있는 것이다
그래서 XAML의 개체들은 정말 흥미로운 것들이다
Button을 하나 그리면 그 안에 또 다른 개체가 수도 없이 만들어 넣을수
있게 되는 것이다
예를 들면 VBA의 UserForm의 Button에 나타나는 문자열은
Button.Caption="MyButton"
이라고 단일 문자열 정보를 표현하는 것 뿐이다
그러나 XAML의 Button은 Caption이라는 단일정보의 속성을 갖지 않고
Button.Content라는 ..즉 Content라는 속성을 갖고 있고
이 Content속에 또 다른 개체를 만들어 넣을수 있다는 점이다
앞으로 나올 것이니까..긴가,민가 상태에서 또 가자..
아무튼 위의 에니메이션 ..TranslateTransform 에이메이션은
위치를 이동하는 에니메이션이다
영어..그냥 단어의 의미 그대로이다..Transform은 변형시킨다는 것이고
Translate는 위치를 이동시키는 것이고..
그래서 Button이 갖고 있는 RenderTransform(변형의 표현)이라는 개체내에는
위치를 이동하는 것( Translate)도 있을수 있고
회전을 시키는 것( Roatate)도 있을수 있고
찌그려뜨리라는 (Skew) 도 있을 수 있고..많은 속성값에 변화를 줄수 있는 것이다
컴퓨터의 에니메이션이라고하는 것은..착각(Illusion)을 불러 일으키는 것이지
별 특별한 것이 아니다..
시간이라는 간격속에서(TimeLine개체)어떤 속성의 값을 일정하게
변화를 주던, 불규칙하게 변화를 주던..변화를 주는 것이 곧 에니메이션인 것이다
그러니 실은 Animation 개체들은 내부적으로 TimeLine개체라는 것을 상속받고 있다
즉 시간을 관리하는 개체..에니메이션은 시간차..변화..
이제 생각이 날 것이다
엑셀에서 VBA를 통하여 어떤 에니메이션을 한다고 치면
순환문을 돌렸다..어떤 숫자값을 계속 반복순환하면서
개체의 위치를 변화시키는 것이 고작이였을 것이다
StoryBoard그리고 그 하위의 Animation 개체들이 하는 일은 바로
우리가 순환문을 짜던가..Application개체의 OnTime 메소드를 사용하던가
하는 구차스러운 일들을 모두 도맡아서 하게 되는 개체들인 것이다
그냥 개발자는 Animation개체가 원하는 에니메이션 대상
그리고 에니메이션하는 개체의 어떤 속성이라는 정보만 전달해주면 되는 것이다
그리고 XAML의 에니메이션은 일정한 시간간격이 아닌..
예를 들면 공이 바닥에 떨어졌다가 다시 튀어 올랐다가
다시 떨어지면 속도가 쭐거나, 늘거나 하여야 자연스러운 에니메이션이 된다
그런 것들을 모두 처리하는 지능 높은 개발도구라는 점!! 그것이 매력인 것이다

아무튼 그래서 위의 Style개체가 갖고 있는 Animation은
DoubleAnimation개체를 사용하고 이 개체가 어떤 것을 에니메이션시키냐는 정보는
아래와 같이 표현되는 것이다

Storyboard.TargetProperty="(Button.RenderTransform).(TranslateTransform.Y)"

Storyboard개체의 TargetProperty라는 속성값에
좀 복잡한 경로가 표현되었다..위에서 이야기 했다 시피..
Button의 RenderTransform의 속성의 또 다른 하위 속성
Translateform속성의 Y 속성값이 에니메이션의 타켓이라는 소리다..
즉 이 Y값을 어떤 시간대에..(Duration 속성..00:00:05, 즉 5초동안)
From=10에서 To=200 까지 변화를 주라는 것이다
AutoReverse=True라는 것은 한번 이동했다가 자동으로 제자리로
다시 돌아오라는 정보가 되는 것이다



같은 요령으로 위의 그림과 같이 다양한 표현을 해 볼수 있을 것이다
옵션버튼을 크릭할때마다 버튼의 Style개체를 다른 것을 주게 되는 것이다
XAML문으로 다양한 Style개체를 만들어 놓고
VB로 RunTime에 Style개체를 다른 것으로 바꿔주면
같은 버튼을 크릭하여도 다양한 행동을 하게 되는 것이다(속성의 변화)

VB로 Style개체를 읽어내는 방법은 위에서 Key값을 준것을 알것이다
이 Key값으로 찾어서 주면 된다
아래와 같이

Me.Button1.Style = CType(Me.FindResource(sStyle), Style)

위의 구문의 빨강색이 Style개체의 키값을 문자열정보로 주면 된다
위의 요령으로 화일내용을 살펴보시면서
속성값을 이렇게, 저렇게 바꿔보면서 해보시면 충분히 이해하시고
활용하실수 있을 것이다

***[LOG-IN]***