TBD… 주의! 작성 중입니다.
2. 색상 표현
? 여러분, WPF를 처음 시작할 때 가장 먼저 배워야 할 것이 무엇일까요?
정해진 순서는 없지만 WPF는 시각적인 UI를 자유롭게 표현할 수 있다는 것이 강점인데요.
그래서 제가 가장 먼저 소개하고 싶은 부분이 바로 색상입니다.
WPF는 색상에 있어 아주 유연하고 자유도 높은 표현력을 자랑해요.
WPF는 생각보다 더 멋지게 색상을 표현할 수 있습니다. 그러기 위해 이 글을 절대 놓치지 마세요!
1. HEX 색상 코드 (16 진수)
모든 개발 언어에서 널리 사용되는 Hexadecimal(16진수)색상 코드는 WPF에서도 사용되는데요. 여기에서는 더욱 더 빛을 발휘합니다.
WPF는 특히 Hexadecimal(16진수)를 통해 색상을 깊이 있게 표현할 수 있는데요.
저는 지금부터 이 것을 HEX 코드라고 지칭하겠습니다.
? 그럼 정말 자주 사용하는 HEX 코드를 통해 읽는 방법을 알아볼까요?
#000000 // Black 블랙
#FFFFFF // White 화이트
WPF에서 가장 많이 사용되는 컬러는 #000000
, #FFFFFF
이 코드일 것입니다.
만약 100% 검정 보다는 조금 덜 어두운 검정색을 원한다면 점점 FF와 가까워지면 됩니다.
HEX |
사용 빈도 |
색상 설명 |
000000 |
자주 사용 |
100% 어두운 블랙 색상 |
010101 |
- |
100%보다 좀 덜 어두운 블랙 색상 (하지만 사람 눈으로는 절대 구분 불가… ) |
252525 |
자주 사용 |
비주얼스튜디오(다크 테마) 배경색 처럼 100% 검정은 아니지만 은은한 진한 블랙 |
666666 |
- |
검정이라 하기 애매한 블랙 색상 |
AAAAAA |
자주 사용 |
점점 화이트에 가까워 지는 색상 |
DDDDDD |
자주 사용 |
촌스럽지 않은 선(Border) 색을 표현할때 이상적인 색상 |
EEEEEE |
자주 사용 |
100% 화이트는 싫을 때 |
FFFFFF |
자주 사용 |
100% 화이트 색상 |
? 그런데 왜 16 진수처럼 보이지 않나요?
사실 이 코드는 16 진수 3 개가 합쳐진 색상 값입니다.
00 + 00 + 00
FF + FF + FF
그리고 이 값들이 16진수에서 → 10진수로 변환할 수도 있습니다.
(이것이 바로 RGB)
WPF에서 표현되는 모든 색상은 RGB 합성 표현색인 Red + Green + Blue 구조를 통해 이루어집니다.
그리고 때로는 HEX 코드를 → RGB로, 또는 RGB를 → HEX 코드 형태로 변환하는 일이 생기는데요.
? 그럼 RGB 형식으로도 한번 변환해볼까요?
000000 -> R: 0, G: 0, B: 0
FFFFFF -> R: 255, G, 255, B: 255
이처럼 HEX 코드와 RGB 값은 서로 변환이 가능한 형태임을 확인합시다!
만약 WPF가 16 진수로 변환한 6 자리 코드를 사용하지 않았다면 최대 9자리 (255 + 255 + 255) 코드형태로 사용했을지도 모르는 일이네요.
? 우선 사용 방법을 살펴볼까요?
XAML 상에서 StackPanel 안에 여러 배경 색상의 Border를 만들어 보겠습니다.
<StackPanel>
<Border Background="#FFFFFF" Width="50" Height="50"/>
<Border Background="#000000" Width="50" Height="50"/>
<Border Background="White" Width="50" Height="50"/>
<Border Background="Black" Width="50" Height="50"/>
</StackPanel>
이처럼 문자열로 간단하게 Background 색상 표현을 할 수 있습니다.
참고로 Brush 속성은 내부적으로 문자열 값을 Brush 객체로 자동으로 변환합니다.
Background(Brush)는 Hex 코드 뿐만 아니라 Brushes 클래스가 제공하는 기본 색상(속성)도 사용이 가능합니다. 또한 Brush에 포함된 IFormattable 인터페이스를 통한 문자열 → Brush 객체 변환(Convert) 처리가 구현되어 있기 때문에 직접 Brush 객체를 만들지 않아도 쉽게 색상을 표현할 수 있습니다.
이 부분이 크게 중요한 부분은 아닐지도 모르지만 실제 소스코드 상에서 .Background를 접근할 때 #FFFFFF과 같은 문자열이 아닌 Brush 객체를 마주하게 될 것이기 때문에 이런 상황을 인지하고 있는 것은 도움될 수 있습니다.
기본적으로 Brushes 클래스에서 Static으로 제공하는 모든 색상(속성)을 Text 형태로 입력할 수 있으며
내부적으로 Brushes.Text 또는 16진수 Hex 값을 Parse 처리하는 internal 기능을 통해 Brush 객체로 변환됩니다. (참고)
? 저는 디자이너 혹은 Blender가 아닌데 이 정도 까지 해야 하나요?
사실 WPF에서는 000000
~ FFFFFF
범위 내의 블랙/화이트 색상만 잘 표현한다면 어두운 계열 (다크 테마) 느낌의 앱도 손쉽게 표현해낼 수가 있습니다.
WPF는 개발자가 쉽게 UI를 표현할 수 있는 것이 장점입니다.
WPF를 유연하게 표현하기 위해 이 HEX 코드에 익숙해지는 것이 중요합니다 !!!
심지어 아래 앱 사진은 겨우 5~6개의 색상 만으로도 보기 좋은 배색을 만들어 낼 수 있습니다.
(참고이미지)
HEX 코드… 너무 중요해서 한번 더 강조 할게요.
보기 좋은 WPF UI는 색상에서 부터 나옵니다.
2. 배경 색상(Background or Fill)
배경 색상은 UI 객체 속성 중에서도 가장 대표적이면서 상징적인 프로퍼티 입니다. 왜냐하면 색상을 표현하는 속성 중에서도 유일하게 모든 UI 객체에 존재하고 있기 때문입니다. (물론 예외도 있지만 대세에 지장 x)
WPF의 배경 색상은 부모 객체의 유형에 따라 Background 또는 Fill 속성으로 제공됩니다.
그리고 이 속성들의 이름은 각각 다르지만 동일한 객체 타입(Brush)임을 확인할 수 있습니다.
프로퍼티 이름 |
타입 (객체) |
선언 형식 |
Background |
Brush |
Brush Background { get; set; } |
Fill |
Brush |
Brush Background { get; set; } |
대부분의 UI는 Background를 사용하지만 Geometry와 관련이 있는 UI(Ellipse, Reactangle, Path 등…)의 경우 Fill을 사용합니다.
다만 둘 다 같은 Brush 객체이기 때문에 표현하는 방식, 사용 방법은 동일합니다.
? 배경 색상을 직접 확인해볼까요?
UI 컨트롤마다 Background(Fill) 속성이 어떤 상위 부모 객체를 통해 존재하는지 의식하고 사용하는 것은 WPF에서의 디자인 구조와 설계 철학을 이해하고 이를 수준 높게 구현하는데 있어 매우 도움이 됩니다.
그렇다면 여러분이 직접 부모 객체를 확인하는 방법에 익숙해져야 합니다.
부모 객체 확인 방법은?
- 속성선택 → F12
- 속성선택 → 또는 우클릭 → 정의로 이동(G)
형식 및 멤버 정의 보기
부모 객체를 찾는 방법에 대해 익숙하지 않다면 반드시 먼저 숙지해야 합니다!!!
? 방법을 숙지했다면 부모 객체를 탐색해볼까요?
UI 객체를 아래와 같이 선언하고 Background(Fill) 속성을 통해 부모 객체를 직접 확인할 수 있습니다.
Grid grid = new();
UserControl userControl = new();
TextBlock textBlock = new();
Ellipse ellipse = new();
ViewBox viewBox = new();
grid.Background = Brushes.Red;
userControl.Background = Brushes.Green;
textBlock.Background = Brushes.Blue;
ellipse.Fill = Brushes.Pink;
여러분이 자주 사용하는 UI 컨트롤의 부모 객체를 확인해보셨나요?
그리고 저는 Background 를 사용하는 모든 UI객체를 조사하여 아래 표로 만들었습니다.
컨트롤이 참 많죠?
(너무 많지만 이번 기회에 저와 함께 전체 목록을 한번 살펴봅시다.)
컨트롤 (UI 객체 클래스) 이름 |
속성 이름 |
부모 객체 |
Grid |
Background |
Panel |
UniformGrid |
Background |
Panel |
Canvas |
Background |
Panel |
InkCanvasInnerCanvas |
Background |
Panel |
StackPanel |
Background |
Panel |
DockPanel |
Background |
Panel |
WrapPanel |
Background |
Panel |
TabPanel |
Background |
Panel |
VirtualizingPanel |
Background |
Panel |
ToolBarOverflowPanel |
Background |
Panel |
Calendar |
Background |
Control |
ContentControl |
Background |
Control |
DataGridColumnFloatingHeader |
Background |
Control |
DataGridRow |
Background |
Control |
DatePicker |
Background |
Control |
FlowDocumentReader |
Background |
Control |
FlowDocumentScrollViewer |
Background |
Control |
ItemsControl |
Background |
Control |
PasswordBox |
Background |
Control |
CalendarItem |
Background |
Control |
DocumentViewerBase |
Background |
Control |
RangeBase |
Background |
Control |
ResizeGrip |
Background |
Control |
TextBoxBase |
Background |
Control |
Thumb |
Background |
Control |
Separator |
Background |
Control |
StickyNoteControl |
Background |
Control |
(ButtonBase) Button |
Background |
Control |
(ButtonBase) GridViewColumnHeader |
Background |
Control |
(ButtonBase) DataGridColumnHeader |
Background |
Control |
(ButtonBase) DataGridRowHeader |
Background |
Control |
(ButtonBase) RepeatButton |
Background |
Control |
(ButtonBase) ToggleButton |
Background |
Control |
(ComboBox) TextBlockComboBox |
Background |
Control |
(ContentControl) DataGridCell |
Background |
Control |
(ContentControl) Frame |
Background |
Control |
(ContentControl) GroupItem |
Background |
Control |
(ContentControl) HeaderedContentControl |
Background |
Control |
(ContentControl) Label |
Background |
Control |
(ContentControl) ListBoxBoxItem |
Background |
Control |
(ContentControl) ButtonBase |
Background |
Control |
(ContentControl) StatusBarItem |
Background |
Control |
(ContentControl) ScrollViewer |
Background |
Control |
(ContentControl) ToolTip |
Background |
Control |
(ContentControl) UserControl |
Background |
Control |
(ContentControl) Window |
Background |
Control |
(TextBoxBase) RichTextBox |
Background |
Control |
(TextBoxBase) TextBox |
Background |
Control |
(HeaderedContentControl) Expander |
Background |
Control |
(HeaderedContentControl) GroupBox |
Background |
Control |
(HeaderedContentControl) TabItem |
Background |
Control |
(HeaderedItemsControl) TreeViewItem |
Background |
Control |
(ItemsControl) HeaderedItemsControl |
Background |
Control |
(ItemsControl) DataGridCellsPresenter |
Background |
Control |
(ItemsControl) DataGridColumnHeaderPresenter |
Background |
Control |
(ItemsControl) MenuBase |
Background |
Control |
(ItemsControl) Selector |
Background |
Control |
(ItemsControl) StatusBar |
Background |
Control |
(ItemsControl) TreeView |
Background |
Control |
(ListBox) ListView |
Background |
Control |
(ListBoxItem) ComboBoxItem |
Background |
Control |
(ListBoxItem) ListViewItem |
Background |
Control |
(MenuBase) ContextMenu |
Background |
Control |
(MenuBase) Menu |
Background |
Control |
(MultiSelector) DataGrid |
Background |
Control |
(Selector) ComboBox |
Background |
Control |
(Selector) ListBox |
Background |
Control |
(Selector) MultiSelector |
Background |
Control |
(Selector) TabControl |
Background |
Control |
(ToggleButton) CheckBox |
Background |
Control |
(ToggleButton) RadioButton |
Background |
Control |
Border |
Background |
Border (Self) |
TextBlock |
Background |
TextBlock (Self) |
Rectangle |
Fill |
Shape |
Ellipse |
Fill |
Shape |
Path |
Fill |
Shape |
Polygon |
Fill |
Shape |
Polyline |
Fill |
Shape |
Line |
Fill |
Shape |
HighlightSegment |
Fill |
Shape |
Background(Fill) 속성은 다음과 같은 상위 객체에서 제공되고 있습니다.
- Panel
- Control
- Border
- TextBlock
- Shape
? 속성을 이렇게 자세하게 살펴봐야 하나요?
아닙니다!! 다만 Background 속성을 통해 모든 UI 객체를 확인하는 것이 의미가 있기 때문에 함께 확인해 본 것입니다.
WPF와 객체 개념에 아직은 능숙하지 않더라도 Background 속성이 어느 부모 객체를 통해 받게 된 것 인지를 계속해서 인지하고 부모 객체의 특성을 이해하려는 시도를 해보는 훈련이 중요합니다!!!
또한 이와 같은 분석 방법을 이용해 앞으로 더 다양한 UI 속성(Content, Margin, Padding 등)에 접근하고 이해하는데 있어 중요한 밑거름이 될 것입니다.