하아찡
CustomTitleBar작업 -1 본문
기존 타이틀바 말고 새롭게 커스텀 하고싶어서 만들어 봤습니다.
결과물

현재까지 구현한 기능은 아이콘 추가, 타이틀명, 최소화, 최대화, 폼 종료까지 구현했습니다.
Window Xaml 코드입니다.
<Window x:Class="TitleBar.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TitleBar"
mc:Ignorable="d"
x:Name="MyForm"
xmlns:rclass="clr-namespace:TitleBar.Themas.ResourceClass"
WindowStyle="None"
BorderThickness="0"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<rclass:CustomTitleBar Icon="/Resources/teddy-bear.ico" Grid.Row="0" WindowForm="{x:Reference MyForm}" HoverBackColor="Beige" TitleName="타이틀바 테스트1" />
<rclass:CustomTitleBar Grid.Row="1" ContentColor="Red" WindowForm="{x:Reference MyForm}" BackColor="AliceBlue" HoverBackColor="#FFCFE7FD" TitleName="타이틀바 테스트2" />
</Grid>
</Window>
기존에 있는 Titlebar를 지우기위해 WindowStyle="None" 을 추가하여 기본으로 제공하는 Titlebar를 제거 했습니다.
CustomControl 이름은 CustomTitleBar라고 작업을 진행 했습니다.
CustomTitleBar.Xaml 코드 입니다.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:rclass="clr-namespace:TitleBar.Themas.ResourceClass"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button" x:Key="Btns">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="{Binding BackColor , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" x:Name="TargetBack">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center">
<ContentPresenter.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{Binding ContentColor , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="TargetBack" Property="Background" Value="{Binding HoverBackColor , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type rclass:CustomTitleBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type rclass:CustomTitleBar}">
<Grid Background="{Binding BackColor , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}">
<Grid.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DragFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" />
</Grid.InputBindings>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding IconWidth , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="{Binding MinimizeButton , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<ColumnDefinition Width="{Binding MinMaxButton , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<ColumnDefinition Width="{Binding CloseButton , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Margin="5,3,5,3" Width="auto">
<Image Grid.Column="0" Width="20" Height="20" Stretch="Fill"
VerticalAlignment="Center" HorizontalAlignment="Center"
Source="{Binding Icon , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"
/>
</StackPanel>
<TextBlock Grid.Column="1" Padding="6,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="14" Foreground="{TemplateBinding ContentColor}"
Text="{Binding TitleName, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<Button Grid.Column="2" Content="ㅡ" Style="{StaticResource Btns}"
Command="{Binding MinimizeFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" />
<Button Grid.Column="3" Content="ㅁ" Style="{StaticResource Btns}"
Command="{Binding MinMaxFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<Button Grid.Column="4" Content="X" Style="{StaticResource Btns}"
Command="{Binding CloseFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
첫번째 x:key="Btns"는 CustomTitleBar에서 최소화, 최대화, 닫기를 모두 버튼을 사용하여 만들어서 스타일 한 개를 만들어 추가하는 방식으로 사용했습니다.
해당 스타일에는 기본적인 배경색, 폰트색상, 호버됐을때 배경색변경하는 이벤트들을 추가 하였습니다.
해당 코드를보면 기본적으로 그냥 Trigger를 사용했을때 호버됐을때 배경색이 변경되지 않아 ControlTemplate으로 새로 만들어 추가해줬습니다.
배경색 변경 및 폰트색 변경쪽 데이터를 받아오기위해 CustomTitleBar 리소스 클래스 코드에 존재하는 값을 바인딩 하기위해 아래와같이 추가해줬습니다.
Background="{Binding BackColor , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"
해당 부분을 보면 하위 요소에서 특정 데이터를 가져오기위해 AncestorType={x:Type 특정데이터를 가지고있는요소} 을 사용하여 특정 데이터를 가져올 수 있습니다.
작업하다 보면 해당 데이터 안에 갇혀 상위 데이터를 가져오지 못할때 사용하면 좋을 듯 합니다.
CustomTitleBar에 대한 내용입니다.
<Style TargetType="{x:Type rclass:CustomTitleBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type rclass:CustomTitleBar}">
<Grid Background="{Binding BackColor , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}">
<Grid.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DragFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" />
</Grid.InputBindings>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding IconWidth , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="{Binding MinimizeButton , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<ColumnDefinition Width="{Binding MinMaxButton , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<ColumnDefinition Width="{Binding CloseButton , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Margin="5,3,5,3" Width="auto">
<Image Grid.Column="0" Width="20" Height="20" Stretch="Fill"
VerticalAlignment="Center" HorizontalAlignment="Center"
Source="{Binding Icon , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"
/>
</StackPanel>
<TextBlock Grid.Column="1" Padding="6,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="14" Foreground="{TemplateBinding ContentColor}"
Text="{Binding TitleName, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<Button Grid.Column="2" Content="ㅡ" Style="{StaticResource Btns}"
Command="{Binding MinimizeFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" />
<Button Grid.Column="3" Content="ㅁ" Style="{StaticResource Btns}"
Command="{Binding MinMaxFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
<Button Grid.Column="4" Content="X" Style="{StaticResource Btns}"
Command="{Binding CloseFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
그리드는 최대 5개로 나눠져있으며,
첫번째 컬럼은 아이콘을 넣어줄 Image를 저장.
두번째 컬럼은 타이틀명을 저장해줄 TextBlock을 저장.
세번째 컬럼은 최소화를 해줄 버튼을 저장.
네번쨰 컬럼은 축소 및 확대를 해줄 버튼을 저장.
다섯번째 컬럼은 해당 폼을 종료 해줄 버튼을 저장.
드래그 이벤트를 작동시킬 타이틀바를 클릭을해야하는데 모든데이터를 묶어주고 있는 Grid에 클릭 이벤트를 추가해줬습니다.
<Grid.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DragFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" />
</Grid.InputBindings>
Grid에 직접적으로 Commad를 사용하지못해 InputBindings라는 속성을 사용해서 MouseBinding을 사용했습니다.
MouseBinding은 아래를 참고하세요.
MouseBinding 클래스 (System.Windows.Input)
MouseGesture를 RoutedCommand 또는 다른 ICommand 구현에 바인딩합니다.
learn.microsoft.com
첫번째 컬럼
<StackPanel Orientation="Horizontal" Margin="5,3,5,3" Width="auto">
<Image Grid.Column="0" Width="20" Height="20" Stretch="Fill"
VerticalAlignment="Center" HorizontalAlignment="Center"
Source="{Binding Icon , RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
</StackPanel>
아이콘 경로를 바인딩을 통해 받아와 아이콘 수정을 편리하게 추가했음.
두번째 컬럼
<TextBlock Grid.Column="1" Padding="6,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="14" Foreground="{TemplateBinding ContentColor}"
Text="{Binding TitleName, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}"/>
TextBlock에 Text에 데이터를 바인딩하여 추가했음.
3~5 컬럼
<Button Grid.Column="2" Content="ㅡ" Style="{StaticResource Btns}"
Command="{Binding MinimizeFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" CommandParameter="{TemplateBinding WindowForm}"/>
<Button Grid.Column="3" Content="ㅁ" Style="{StaticResource Btns}"
Command="{Binding MinMaxFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" CommandParameter="{TemplateBinding WindowForm}"/>
<Button Grid.Column="4" Content="X" Style="{StaticResource Btns}"
Command="{Binding CloseFormCommand, RelativeSource={RelativeSource AncestorType={x:Type rclass:CustomTitleBar}}}" CommandParameter="{TemplateBinding WindowForm}"/>
최소화, 축소 및 최대화, 종료버튼을 추가해줌.
스타일은 맨위에서 작성한 스타일을 추가해서 사용했습니다.
여기까지 CustomTitleBar.Xaml 코드였습니다.
다음편에는 Cs코드를 살펴보겠습니다.
'WPF > XAML조각모음' 카테고리의 다른 글
CustomTitleBar작업 -2(완) (0) | 2023.08.18 |
---|---|
XAML TextBox에 TextBlock을 사용하여 PlaceHolder를 추가함. - 3 (0) | 2023.08.05 |
XAML TextBox에 TextBlock을 사용하여 PlaceHolder를 추가함. - 2 (0) | 2023.08.03 |
XAML TextBox에 TextBlock을 사용하여 PlaceHolder를 추가함. - 1 (0) | 2023.08.03 |
WPF XAML 작업중 헷갈리는 내용을 끄적이는곳 (0) | 2023.08.03 |