WPF 컨트롤 생성에 있어 Round Button 컨트롤을 만드는 작업은 필수적으로 거치는 단계인듯하다. 가장 자주 사용되고 접근하기 쉬운 컨트롤이 Button이고, 요즘 UI들은 각진 버튼을 보기 어렵기 때문이다. Round Button을 구현함으로써 Style 생성 및 적용 방법과 컨트롤 구현 방법에 대해 알 수 있고, 다른 컨트롤을 생성하기 위한 힌트(아이디어)를 얻을 수 있다.
기본적으로 Button에는 CornerRadius 속성이 없다. 따라서 Button에 Style을 적용, ControlTemplate을 통해 Button의 형태를 재정의한다. 아래 코드는 CornerRadius = 3인 Round Button을 만든 코드이다. ControlTemplate 내부 코드를 보면 먼저 Border를 생성하고, Border 내부에 ContentPresenter를 생성하여 버튼과 유사한 형태가 되도록 만들어준다. 그리고 Border에 CornerRadius 값을 정의함으로써 Round Button을 생성한다.
Border는 CornerRadius 속성을 가지고 있기 때문에, 적절한 CornerRadius 값을 입력하면 된다. 버튼의 Background는 Border의 Background를 사용한다. 글자 색상은 ContentPresenter에서 TextElement.Foreground 값으로 정의한다. ContentPresenter의 TextElement는 FontSize, FontFamily, FontStretch, FontStyle, FontWeight, Foreground 속성을 가지며, Background 값은 가지고 있지 않다. Border 및 ContentPresenter에 x:Name을 설정한 이유는 아래에 조금 더 자세하게 설명하였다.
<Grid>
<Button x:Name="botton_Test" Content="Test Button"
Width="200" Height="25" IsEnabled="True">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" CornerRadius="3" Background="Blue">
<ContentPresenter x:Name="contentPresenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextElement.Foreground="White" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Grid>
이렇게 Border와 ContentPresenter를 이용한 Round Button을 생성하고나면 의문이 발생한다. 웹 사이트나 Application에서 버튼을 떠올려보면, 마우스가 버튼 위에 올라갔을 때나 버튼을 클릭했을 때에 버튼 색 또는 글자 색이 변경되면서 사용자에게 버튼이 어떤 동작을 수행한다는 인식을 하게끔 알려준다.
하지만 조금 전 생성한 버튼을 동작해보면 클릭했다는 느낌이 없다. 사용자가 마우스를 버튼 위에 올려두었다는, 또는 버튼을 클릭했다는 느낌을 주려면 Trigger를 이용하여 특정 이벤트가 발생되었을 때 Button의 속성(Border와 ContentPresenter)을 변경해주어야 한다.
아래 코드를 보면 조금 전 생성한 Round Button에 Trigger 속성을 추가한 것을 확인할 수 있다. Trigger는 '어느 특정한 동작에 반응해 자동으로 필요한 동작을 실행하는 것' 을 의미한다. 아래 코드를 바탕으로 이해하자면 입력한 Property에 대하여 Value가 충족되었을 경우, Setter에 표기된 동작을 수행한다는 뜻이다.
Trigger를 이용하여 버튼이 비활성화(IsEnabled = False) 되었을 경우, 마우스가 버튼 위로 올라갔을 경우(IsMouseOver = True), 버튼을 클릭했을 경우(IsPressed = True)에 대한 코드를 작성했다. 3가지 동작에 대해 각각 Trigger를 작성했으며, 해당 Trigger의 조건이 충족된 경우 Border 또는 ContentPresenter, 혹은 두 컨트롤 모두에 특정 속성을 변경해주었다.
<Grid>
<Button x:Name="botton_Test" Content="Test Button"
Width="200" Height="25" IsEnabled="True">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" CornerRadius="3" Background="Blue">
<ContentPresenter x:Name="contentPresenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextElement.Foreground="White" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.35"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border"
Property="Background"
Value="CornflowerBlue"/>
<Setter TargetName="contentPresenter"
Property="TextElement.Foreground"
Value="Black"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border"
Property="Background"
Value="MediumBlue"/>
<Setter TargetName="contentPresenter"
Property="TextElement.Foreground"
Value="White"/>
<Setter TargetName="contentPresenter"
Property="TextElement.FontWeight"
Value="Bold"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Grid>
Trigger 내부의 Setter에는 Property와 Value, TargetName이 사용되었다. Property는 변경하려는 속성이고, Value는 변경하려는 속성값이다. TargetName은 특정 컨트롤의 Property만 변경하려는 경우 사용되며, TargetName이 설정되지 않은 경우 Control 자체(여기서는 Button)에 적용된다.
제시된 예에서 Trigger는 하나의 조건에 대해서면 동작을 수행한다. 조금 더 복잡하고 다양한 컨트롤의 집합으로 된 컨트롤이 존재한다면, 하나의 조건으로만 특정 동작을 수행하기에는 답답할 수 있다. 여러 조건이 충족될 때 특정 동작을 수행하도록 만들려면 MultiTrigger를 사용하면 된다.
MultiTrigger는 이후에 따로 작성할 예정.
끝!
'프로그래밍 언어 > WPF' 카테고리의 다른 글
[C#] WPF - 사용자 정의 컨트롤(User Control) / 사용자 지정 컨트롤(Custom Control) (0) | 2024.01.09 |
---|---|
[C#] WPF - UI의 모든 컨트롤 가져오기 (0) | 2024.01.05 |
[C#] WPF - 토글 스위치(Toggle Switch) 생성 (2) | 2023.12.26 |
[C#] WPF - 특정 프로세스 Focus 여부 판단 방법 (0) | 2023.01.09 |
[C#] WPF - DataGrid의 ForeColor 변경 시 에러 방지 (2) | 2022.10.26 |
댓글