이번시간에는 XAML만을 사용하여 쇼핑몰 등에서 사용 가능한 Detail View를 구현해보도록 하겠습니다. (이번에도 역시 정확한 이름짖기가 애매해서 -_- Detail View라고 했습니다.) 아래는 시연 동영상 입니다.
제가 좋아하는 만화중에 하나인 드래곤볼입니다ㅎㅎ 기능에 대해서 설명하자면 화면 왼쪽에는 손오공이 오른쪽에는 베지터라는 메뉴가 있습니다. 해당 메뉴에 마우스를 오버 할 경우 해당 메뉴에서 더 보여주고 싶은 자세한 내용을 포함 할 수 있습니다. 소스코드를 본 뒤 더 자세히 이야기를 해보겠습니다.
- <WINDOW title="DragonBall - WPFKOREA(http://whatisthat.co.kr)" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="DragonBall.Window1" Width="600" Height="400">
- <WINDOW.RESOURCES>
- <IMAGEBRUSH x:Key="Background" ImageSource="Background.jpg" />
- <STYLE TargetType="Button" x:Key="ProfileBox">
- <Style.Resources>
- <Style TargetType="TextBlock">
- <Setter Property="Foreground" Value="White"/>
- <Setter Property="TextAlignment" Value="Center"/>
- <Setter Property="FontSize" Value="11"/>
- <Setter Property="FontFamily" Value="Trebuchet MS"/>
- <Setter Property="VerticalAlignment" Value="Center"/>
- <Setter Property="HorizontalAlignment" Value="Center"/>
- <Setter Property="Cursor" Value="Hand"/>
- </STYLE>
- </STYLE.RESOURCES>
- <SETTER Value="Black" Property="Background" />
- <SETTER Value="55" Property="Width" />
- <SETTER Value="17.5" Property="Height" />
- <SETTER Property="Template">
- <SETTER.VALUE>
- <CONTROLTEMPLATE>
- <GRID Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Background="{TemplateBinding Background}">
- <TEXTBLOCK Text="{TemplateBinding Tag}" />
- <CONTENTPRESENTER x:Name="ContentBase" Opacity="0" Content="{TemplateBinding Button.Content}" />
- </GRID>
- <CONTROLTEMPLATE.TRIGGERS>
- <TRIGGER Value="True" Property="Button.IsMouseOver">
- <TRIGGER.ENTERACTIONS>
- <BEGINSTORYBOARD>
- <STORYBOARD Storyboard.TargetName="ContentBase">
- <DOUBLEANIMATION Storyboard.TargetProperty="(Grid.Height)" Duration="0:0:0.5" To="175" />
- <DOUBLEANIMATION Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:0.5" To="142.5" />
- <DOUBLEANIMATION Storyboard.TargetProperty="Opacity" Duration="0:0:0.5" To="1" />
- </STORYBOARD>
- </BEGINSTORYBOARD>
- </TRIGGER.ENTERACTIONS>
- <TRIGGER.EXITACTIONS>
- <BEGINSTORYBOARD>
- <STORYBOARD Storyboard.TargetName="ContentBase">
- <DOUBLEANIMATION Storyboard.TargetProperty="(Grid.Height)" Duration="0:0:0.5" To="17.5" />
- <DOUBLEANIMATION Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:0.5" To="300" />
- <DOUBLEANIMATION Storyboard.TargetProperty="Opacity" Duration="0:0:0.5" To="0" />
- </STORYBOARD>
- </BEGINSTORYBOARD>
- </TRIGGER.EXITACTIONS>
- </TRIGGER>
- </CONTROLTEMPLATE.TRIGGERS>
- </CONTROLTEMPLATE>
- </SETTER.VALUE>
- </SETTER>
- </STYLE>
- <STYLE TargetType="Button" x:Key="LeftProfileBox" BasedOn="{StaticResource ProfileBox}">
- <Style.Triggers>
- <Trigger Property="IsMouseOver" Value="True">
- <Trigger.EnterActions>
- <BeginStoryboard>
- <Storyboard>
- <DoubleAnimation To="200" Duration="0:0:0.5" BeginTime="0:0:0.5" Storyboard.TargetProperty="(Grid.Width)"/>
- <DoubleAnimation To="30" Duration="0:0:0.5" BeginTime="0:0:0.5" Storyboard.TargetProperty="(Canvas.Left)"/>
- </Storyboard>
- </BeginStoryboard>
- </Trigger.EnterActions>
- <Trigger.ExitActions>
- <BeginStoryboard>
- <Storyboard>
- <DoubleAnimation To="55" Duration="0:0:0.5" BeginTime="0:0:0.5" Storyboard.TargetProperty="(Grid.Width)"/>
- <DoubleAnimation To="175" Duration="0:0:0.5" BeginTime="0:0:0.5" Storyboard.TargetProperty="(Canvas.Left)"/>
- </Storyboard>
- </BeginStoryboard>
- </Trigger.ExitActions>
- </Trigger>
- </Style.Triggers>
- </STYLE>
- <STYLE TargetType="Button" x:Key="RightProfileBox" BasedOn="{StaticResource ProfileBox}">
- <Style.Triggers>
- <Trigger Property="IsMouseOver" Value="True">
- <Trigger.EnterActions>
- <BeginStoryboard>
- <Storyboard>
- <DoubleAnimation To="200" Duration="0:0:0.5" BeginTime="0:0:0.5" Storyboard.TargetProperty="(Grid.Width)"/>
- </Storyboard>
- </BeginStoryboard>
- </Trigger.EnterActions>
- <Trigger.ExitActions>
- <BeginStoryboard>
- <Storyboard>
- <DoubleAnimation To="55" Duration="0:0:0.5" BeginTime="0:0:0.5" Storyboard.TargetProperty="(Grid.Width)"/>
- </Storyboard>
- </BeginStoryboard>
- </Trigger.ExitActions>
- </Trigger>
- </Style.Triggers>
- </STYLE>
- </WINDOW.RESOURCES>
- <GRID>
- <CANVAS Width="511" Height="328" Background="{StaticResource Background}">
- <BUTTON style="StaticResource: " Tag="Son Goku" Canvas.Top="300" Canvas.Left="175">
- <IMG height=175 width=200 Source="Goku.jpg">
- </BUTTON>
- <BUTTON style="StaticResource: " Tag="Vegeta" Canvas.Top="300" Canvas.Left="275">
- <IMG height=175 width=200 Source="Vegeta.jpg">
- </BUTTON>
- </CANVAS>
- </GRID>
- </WINDOW>
코드가 급하게 포스팅한 내용이라 코드가 상당히 지저분 하지만 전반적인 작동원리에 대해서 이해하시는데에는 크게 문제는 없을 것 같습니다. 메뉴는 기본적으로 Button을 사용하기 때문에 Button의 Style을 적용합니다. MouseOver상태에 따라서 보여줄 객체를 정하기 위해서 Trigger에 IsMouseOver Property를 적용했습니다. 두 매뉴가 확장댈때의 위치가 다르기 때문에 Left와 Right를 기존의 Style을 상속받아 확장될때의 크기를 다시 적용했습니다.
- <GRID Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Background="{TemplateBinding Background}">
- <TEXTBLOCK Text="{TemplateBinding Tag}" />
- <CONTENTPRESENTER x:Name="ContentBase" Opacity="0" Content="{TemplateBinding Button.Content}" />
- </GRID>
Button Style부분의 코드입니다. 작은 상태에서의 보여줄 텍스트는 Tag를 Template Binding하여 표현하고 확장됬을경우 보여줄 컨텐츠를 보여주기 위해 ContentPresenter를 사용했습니다. ContentPresenter의 경우 기본적으로 Opacity가 0이여서 출력되지 않으며 MouseOver시에 Opacity가 변경됩니다.
- <BUTTON style="StaticResource: " Tag="Son Goku" Canvas.Top="300" Canvas.Left="175">
- <IMG height=175 width=200 Source="Goku.jpg">
- </BUTTON>
- <BUTTON style="StaticResource: " Tag="Vegeta" Canvas.Top="300" Canvas.Left="275">
- <IMG height=175 width=200 Source="Vegeta.jpg">
- </BUTTON>
사용할 때는 위와 같이 Tag Property에 버튼의 이름을 정의하고 Content Property에 Detail View에서의 컨텐츠를 추가 하면됩니다. 급하게 포스팅하느라 내용이 약간 어수선 한 부분이 있지만 시간이 되면 다시 정리하도록 하겠습니다. 자세한 내용이나 질문은 댓글이나 메일로 보내주시기 바랍니다.