WPF 컨트롤의 6가지 유형

WPF 컨트롤 분류:

  • 콘텐츠 컨트롤
  • 헤더 콘텐츠 컨트롤
  • 텍스트 컨트롤
  • 리스트 컨트롤
  • 범위 기반 컨트롤
  • 날짜 컨트롤

컨트롤 클래스

컨트롤은 사용자와 상호작용하는 요소입니다. 포커스를 받을 수 있고, 키보드나 마우스 입력을 처리할 수 있습니다.

모든 컨트롤의 기본 클래스는 System.Windows.Control입니다. 이 클래스는 다음과 같은 기능을 포함합니다:

  • 정렬
  • 탭 시퀀스
  • 배경, 전경, 테두리
  • 텍스트 내용의 글꼴

배경 및 전경 브러시

컨트롤은 BackgroundForeground 속성을 가지고 있으며, 이 속성은 Brush 객체를 사용합니다. 브러시 객체의 파생 클래스에는 SolidColorBrush, LinearGradientBrush, TileBrush가 있습니다.

코드로 색상 설정

명이 btnSubmit인 버튼에 배경색을 설정하는 예시:

btnSubmit.Background = new SolidColorBrush(Colors.LightBlue);

Colors 클래스의 정적 속성을 통해 사전 정의된 색상을 얻고, 생성자에 전달하여 새로운 SolidColorBrush 인스턴스를 생성한 후 버튼의 배경 속성에 할당합니다.

시스템 색상을 사용하는 경우:

btnSubmit.Background = new SolidColorBrush(SystemColors.WindowColor);

SystemColors 클래스는 미리 정의된 SolidColorBrush 객체를 반환하는 속성을 제공합니다:

btnSubmit.Background = SystemColors.WindowBrush;

R, G, B 값(레드, 그린, 블루)을 기반으로 색상 객체를 생성할 수 있습니다. 각 값은 0에서 255 사이의 숫자입니다:

int red = 0; int green = 255; int blue = 0;
btnSubmit.Foreground = new SolidColorBrush(Color.FromRgb(red, green, blue));

알파 값으로 색상의 투명도를 설정할 수 있습니다. 알파 값이 255일 때는 완전히 불투명하고, 0일 때는 완전히 투명합니다.

XAML로 색상 설정

XAML에서는 색상 이름이나 값을 제공하면 되며, 나머지는 파서가 처리합니다.

<Button Background="Blue">버튼</Button>

#rrggbb 또는 #aarrggbb 형식으로 색상 값을 제공할 수 있습니다:

<Button Background="#FF0000FF">버튼</Button>

브러시는 자동 변경 통지를 지원합니다. 브러시는 System.Windows.Freezable 클래스에서 파생됩니다. Freezable 클래스는 읽기 전용(고정) 상태와 수정 가능한 상태가 있습니다.

컨트롤 클래스는 BorderBrushBorderThickness 속성을 정의합니다.

글꼴

Control 클래스는 여러 글꼴 관련 속성을 정의합니다. 이 속성들은 컨트롤의 텍스트 외관을 결정합니다. 표 6-1에 해당 속성들이 나열되어 있습니다.

이름 설명
FontFamily
FontSize
FontStyle
FontWeight
FontStretch

Control 클래스는 자체 글꼴 사용 속성을 정의하지 않습니다. 그러나 많은 컨트롤은 Text 속성을 가지고 있으며, 이 속성은 Control 기본 클래스의 멤버가 아닙니다. 명확하게, 글꼴 속성은 파생 클래스에서 사용될 때만 의미가 있습니다.

글꼴 가족

마우스 커서

콘텐츠 컨트롤

콘텐츠 컨트롤은 단일 콘텐츠를 보유하고 표시할 수 있는 특수한 컨트롤 유형입니다. 기술적으로, 콘텐츠 컨트롤은 단일 내부 요소를 포함할 수 있는 컨트롤입니다. 콘텐츠 컨트롤과 레이아웃 컨테이너의 차이는, 콘텐츠 컨트롤은 단일 자식 요소만 포함할 수 있고, 레이아웃 컨테이너는 임의의 수의 자식 요소를 포함할 수 있다는 점입니다.

물론 여러 콘텐츠를 콘텐츠 컨트롤에 넣을 수 있습니다. 방법은 모든 요소를 단일 컨테이너(예: StackPanel 또는 Grid)로 감싸는 것입니다. 예를 들어, Window 클래스 자체는 콘텐츠 컨트롤입니다. 분명히, 창은 일반적으로 많은 콘텐츠를 가지고 있지만, 이 모든 콘텐츠는 상위 컨테이너(보통 Grid)에 패키징됩니다.

모든 콘텐츠 컨트롤은 ContentControl 추상 클래스에서 파생됩니다. 콘텐츠 컨트롤 클래스에는 Label, ToolTip, Button, RadioButton, CheckBox, ScrollViewer, UserControl, Window 등이 포함됩니다.

또한 HeaderedContentControl 클래스에서 파생된 콘텐츠 컨트롤 하위 집합도 존재합니다. 이 컨트롤은 제목 영역과 콘텐츠 영역을 모두 가지며, 제목 영역은 특정 제목을 표시합니다. GroupBox, TabItem, Expander 컨트롤이 이에 해당합니다.

탐색을 위한 Frame, 다른 컨트롤 내부에 사용되는 ListBoxItem, StatusBarItem 등도 콘텐츠 컨트롤입니다.

Content 속성

ContentControl 클래스는 Content 속성을 추가합니다. 이 속성은 단일 개체를 받습니다. Content 속성은 모든 유형의 개체를 지원하지만, 개체를 두 그룹으로 나누고 다르게 처리합니다:

  • UIElement를 상속받지 않은 개체: 콘텐츠 컨트롤은 이 개체에 ToString()을 호출하여 텍스트를 얻고, 이를 표시합니다.
  • UIElement를 상속받은 개체: 이 개체는 모든 시각적 요소를 포함합니다. UIElement.OnRender() 메서드를 사용하여 콘텐츠 컨트롤 내부에 표시됩니다.

예를 들어, 단순한 문자열을 제공하는 버튼:

<Button Margin="3">텍스트 콘텐츠</Button>

이미지를 버튼 내부에 배치하는 예시:

<Button Margin="3">
  <Image Source="smile.png" Stretch="None" />
</Button>

이미지와 텍스트를 포함한 컨테이너를 버튼 내부에 배치하는 예시:

<Button Margin="3">
  <StackPanel>
    <TextBlock Margin="3">이미지 및 텍스트 버튼</TextBlock>
    <Image Source="smile.png" Stretch="None" />
    <TextBlock Margin="3">StackPanel 제공</TextBlock>
  </StackPanel>
</Button>

버튼 내부에 다른 콘텐츠 컨트롤(예: 텍스트 박스, 버튼, 콤보 박스)을 배치할 수 있지만, 이는 일반적으로 비합리적입니다. 그러나 WPF는 이를 허용합니다.

Window는 콘텐츠 컨트롤이지만, 최상위 컨테이너로만 사용할 수 있으며, 다른 요소 내부에 중첩할 수 없습니다.

콘텐츠 컨트롤의 다른 속성에는 HasContent 속성이 있습니다. 이 속성이 true일 때 컨트롤에 콘텐츠가 있음을 나타냅니다. ContentTemplate 속성은 컨트롤이 개체를 어떻게 표시할지 지정하는 템플릿입니다. ContentTemplate을 사용하면 UIElement를 상속받지 않은 개체를 더 지능적으로 표시할 수 있습니다. 개체의 다양한 속성 값을 얻어 더 복잡한 마크업에 배치할 수 있습니다.

콘텐츠 정렬

HorizontalContentAlignment, VerticalContentAlignment의 값은 Top, Bottom, Left, Right, Center, Stretch입니다.

Padding 속성은 컨트롤 테두리와 콘텐츠 간의 거리를 나타냅니다.

HorizontalContentAlignment, VerticalContentAlignment, Padding 속성은 Control 클래스에 정의되어 있으며, 더 특수한 ContentControl 클래스에 정의되지 않습니다. 왜냐하면, 콘텐츠 컨트롤이 아닌 컨트롤도 일부 콘텐츠를 가지기 때문입니다. 예를 들어, TextBox는 콘텐츠 컨트롤이 아니지만, 위의 속성을 사용하여 입력 텍스트를 설정합니다.

WPF 콘텐츠 철학

콘텐츠 컨트롤은 컨트롤 수를 줄이지만, 컨트롤의 복잡도를 약간 증가시킵니다.

라벨(Label)

라벨 컨트롤의 주요 기능은 단축키를 통해 연결된 컨트롤에 포커스를 줄 수 있는 것입니다. 라벨 컨트롤의 Target 속성은 연결된 컨트롤을 지정합니다. Target을 설정하기 위해 다른 컨트롤을 가리키는 바인딩 표현식을 사용합니다.

<Label Target="{Binding ElementName=txtInput}">입력 _A</Label>
<TextBox Name="txtInput"></TextBox>
<Label Target="{Binding ElementName=txtValue}">값 _B</Label>
<TextBox Name="txtValue"></TextBox>

라벨 텍스트의 밑줄은 단축키를 나타냅니다. 실제 밑줄이 필요한 경우 두 개의 밑줄을 연속으로 입력하여 전환합니다.

Alt 키와 지정된 단축키를 동시에 누르면 연결된 컨트롤에 포커스가 이동합니다. 예를 들어, 이 예제에서 Alt+A를 누르면 txtInput 컨트롤에 포커스가 이동합니다.

단축키 기능이 필요하지 않은 경우 TextBlock을 고려할 수 있습니다.

버튼 계열 컨트롤

버튼 계열 컨트롤에는 Button, CheckBox, RadioButton가 포함됩니다. 이들은 모두 ButtonBase에서 파생됩니다.

Click 이벤트는 명령 기능을 지원합니다.

ClickMode 속성은 ClickMode.Release, ClickMode.Press, ClickMode.Hover 값을 가집니다.

버튼은 단축키를 지원합니다.

버튼

각 창에는 취소 버튼과 기본 버튼이 있으며, 버튼의 IsCancel, IsDefault 속성을 설정하여 지정할 수 있습니다. 159 페이지 참조.

또한 IsDefaulted 속성은 혼동하기 쉬운 속성으로, 160 페이지의 옆면 링크 참조.

ToggleButton, RepeatButton

ButtonBase에서 파생된 클래스에는 다음 세 가지가 포함됩니다:

  • GridViewColumnHeader
  • RepeatButton
  • ToggleButton

RepeatButtonToggleButtonSystem.Windows.Controls.Primitives 네임스페이스에 위치합니다. 조합되거나 다른 컨트롤로 파생될 수 있으며, 독립적으로 사용할 수도 있습니다.

CheckBox

CheckBoxRadioButton는 모두 ToggleButton에서 파생됩니다.

ToggleButtonIsChecked 속성을 추가합니다. 이 속성은 null 가능한 부울 값입니다.

WPF 마크업에서 null 값을 할당하려면 빈 마크업 확장을 사용합니다. 예시:

<CheckBox IsChecked="{x:Null}">중간 상태의 체크 박스</CheckBox>

ToggleButtonIsThreeState 속성을 가지며, 이 속성은 체크 박스가 중간 상태로 설정될 수 있는지 여부를 결정합니다. 기본값은 false입니다.

ToggleButton 클래스는 세 이벤트를 정의합니다: Checked, Unchecked, Indeterminate 이벤트.

RadioButton

기본적으로 라디오 버튼은 그룹을 기준으로 그룹화됩니다. RadioButtonGroupName 속성을 사용하면 이 동작을 재정의할 수 있습니다.

<StackPanel>
  <GroupBox Margin="5">
    <StackPanel>
      <RadioButton>그룹 1</RadioButton>
      <RadioButton>그룹 1</RadioButton>
      <RadioButton>그룹 1</RadioButton>
      <RadioButton Margin="0,10,0,0" GroupName="Group2">그룹 2</RadioButton>
    </StackPanel>
  </GroupBox>
  <GroupBox Margin="5">
    <StackPanel>
      <RadioButton>그룹 3</RadioButton>
      <RadioButton>그룹 3</RadioButton>
      <RadioButton>그룹 3</RadioButton>
      <RadioButton Margin="0,10,0,0" GroupName="Group2">그룹 2</RadioButton>
    </StackPanel>
  </GroupBox>
</StackPanel>

GroupBox 컨테이너로 라디오 버튼 그룹을 감싸지 않아도 되지만, 이는 일반적인 관습입니다. GroupBox은 경계와 제목을 표시합니다.

특수 컨테이너

콘텐츠 컨트롤에는 몇 가지 특수 컨테이너도 포함됩니다.

ScrollViewerContentControl에서 직접 상속됩니다.

ContentControl 클래스는 HeaderedContentControl 클래스를 파생시킵니다. 이 클래스는 제목과 콘텐츠를 모두 가지며, 제목과 콘텐츠는 모두 단일 자식 요소를 포함할 수 있습니다. HeaderedContentControl 클래스는 GroupBox, TabItem, Expander 등의 하위 클래스를 파생시킵니다.

ScrollViewer

ScrollViewer는 어떤 요소든 감쌀 수 있지만, 일반적으로 레이아웃 컨테이너를 감쌉니다.

<ScrollViewer>
  <Grid Margin="3,3,10,3">
  </Grid>
</ScrollViewer>

VerticalScrollBarVisibility 속성은 ScrollBarVisibility 열거형입니다. Visible, Auto, Disabled 값이 있습니다. 기본값은 Visible입니다.

HorizontalScrollBarVisibility 속성의 기본값은 Hidden입니다.

프로그래밍으로 스크롤 제어

171페이지 참조.

커스터마이징 스크롤

172페이지 참조.

GroupBox

GroupBoxHeaderedContentControl 클래스에서 파생됩니다.

<GroupBox Header="그룹박스 테스트" Padding="5"
  Margin="5" VerticalAlignment="Top">
  <StackPanel>
    <RadioButton Margin="3">첫 번째</RadioButton>
    <RadioButton Margin="3">두 번째</RadioButton>
    <RadioButton Margin="3">세 번째</RadioButton>
    <Button Margin="3">저장</Button>
  </StackPanel>
</GroupBox>

GroupBox은 여전히 레이아웃 컨테이너를 사용하여 콘텐츠를 배치해야 합니다. GroupBox에는 특별한 기능이 없으며, 단지 장식용 컨트롤입니다.

TabItem

TabItemTabControl의 탭을 나타냅니다. TabItem 클래스는 IsSelected 속성을 추가하여 탭이 TabControl에서 현재 표시되는 탭인지 여부를 나타냅니다.

<TabControl Margin="5">
  <TabItem Header="탭 하나">
    <StackPanel Margin="3">
      <CheckBox Margin="3">설정 1</CheckBox>
      <CheckBox Margin="3">설정 2</CheckBox>
      <CheckBox Margin="3">설정 3</CheckBox>
    </StackPanel>
  </TabItem>
  <TabItem Header="탭 두개"></TabItem>
</TabControl>

TabControlTabStripPlacement 속성을 설정하여 탭을 정상적인 상단에서 측면으로 이동할 수 있습니다.

Content 속성과 마찬가지로, Header 속성은 어떤 유형의 개체라도 받을 수 있습니다. 예시:

<TabControl Margin="5">
  <TabItem>
    <TabItem.Header>
      <StackPanel>
        <TextBlock Margin="3">이미지 및 텍스트 탭 제목</TextBlock>
        <Image Source="smile.png" Stretch="None" />
      </StackPanel>
    </TabItem.Header>

    <StackPanel Margin="3">
      <CheckBox Margin="3">설정 1</CheckBox>
      <CheckBox Margin="3">설정 2</CheckBox>
      <CheckBox Margin="3">설정 3</CheckBox>
    </StackPanel>
  </TabItem>

  <TabItem Header="탭 두개"></TabItem>
</TabControl>

Expander

175페이지 참조.

텍스트 컨트롤

WPF에는 세 가지 텍스트 입력 컨트롤이 있습니다: TextBox, RichTextBox, PasswordBox. PasswordBoxControl에서 직접 파생됩니다. TextBoxRichTextBox 컨트롤은 TextBoxBase에서 파생됩니다.

내용 컨트롤과 달리, 텍스트 박스는 포함할 수 있는 콘텐츠 유형이 제한됩니다. TextBox는 항상 문자열(Text 속성)을 저장합니다. PasswordBoxPassword 속성으로 문자열 콘텐츠를 처리하지만, 이는 SecureString을 사용합니다. 오직 RichTextBox만이 더 복잡한 콘텐츠, 즉 FlowDocument를 저장할 수 있습니다.

다중 줄 텍스트

MaxLength 속성은 TextBox가 허용하는 최대 문자 수를 설정합니다.

TextWrapping 속성은 Wrap 또는 WrapWithOverflow로 설정되어 자동 줄바꿈을 나타냅니다.

MinLinesMaxLines 속성은 TextBox의 최소(최대) 표시 줄 수를 설정합니다.

LineCount 속성은 텍스트 박스에 있는 텍스트 줄 수를 검색할 수 있습니다.

VerticalScrollBarVisibility, HorizontalScrollBarVisibility 속성은 스크롤바의 시각적 상태를 설정합니다.

AcceptsReturn 속성은 TextBox가 줄바꿈을 받아들이는지 여부를 설정합니다. 기본적으로, TextBox는 줄바꿈을 받아들이지 않습니다.

AcceptsTab 속성은 Tab 키를 받아들이는지 여부를 설정합니다. 기본적으로, TextBoxTab 키를 받아들이지 않습니다.

IsReadOnly 속성은 텍스트 편집을 방지합니다.

텍스트 선택

180페이지 참조.

맞춤법 검사

181페이지 참조.

비밀번호 박스

183페이지 참조.

리스트 컨트롤

리스트 컨트롤의 기본 클래스는 ItemsControl 클래스입니다.

ItemsControl 클래스는 항목 목록을 가지고 있습니다. 항목 목록을 채우는 두 가지 방법이 있습니다. 가장 직관적인 방법은 코드 또는 XAML을 사용하여 항목을 직접 항목 집합에 추가하는 것입니다. 더 일반적인 방법은 데이터 바인딩입니다. 이 방법은 ItemsSource 속성을 표시할 데이터 항목 집합으로 설정합니다.

ItemsControl 클래스에서 파생된 주요 분지는 Selector 클래스로, ListBox, ComboBox, TabControl 클래스가 포함됩니다. 현재 선택 항목(SelectedItem) 또는 위치(SelectedIndex)를 추적할 수 있습니다.

나머지 리스트 클래스는 현재 항목을 지원하지 않으며, ItemsControl 클래스에서 직접 파생됩니다. 이러한 클래스에는 Menu, Toolbar, TreeView 등이 포함됩니다.

ListBox

SelectionMode 속성을 Multiple로 설정하면 다중 선택이 가능합니다. 다중 선택 모드에서는 SelectedItem 대신 SelectedItems 집합을 사용해야 합니다.

리스트 박스 항목 추가:

<ListBox>
  <ListBoxItem>녹색</ListBoxItem>
  <ListBoxItem>파랑</ListBoxItem>
  <ListBoxItem>노랑</ListBoxItem>
  <ListBoxItem>빨강</ListBoxItem>
</ListBox>

ListBoxItemContentControl에서 파생됩니다.

이미지 목록 박스 생성 예시:

<ListBox>
  <ListBoxItem>
    <Image Source="smile.png"></Image>
  </ListBoxItem>
  <ListBoxItem>
    <Image Source="smile.png"></Image>
  </ListBoxItem>
</ListBox>

위 예제에서 ListBoxItem을 생략할 수 있으며, 리스트 박스는 목록 항목을 인식하는 충분한 지능을 가지고 있습니다:

<ListBox>
  <StackPanel Orientation="Horizontal">
    <Image Source="smile.png" Width="30" Height="30"></Image>
    <Label VerticalContentAlignment="Center">기분 좋은 표정</Label>
  </StackPanel>
  
  <StackPanel Orientation="Horizontal">
    <Image Source="warning.png" Width="30" Height="30"></Image>
    <Label VerticalContentAlignment="Center">경고 표시</Label>
  </StackPanel>
  
  <StackPanel Orientation="Horizontal">
    <Image Source="smile.png" Width="30" Height="30"></Image>
    <Label VerticalContentAlignment="Center">기분 좋은 표정</Label>
  </StackPanel>
</ListBox>

다음은 체크박스가 리스트 항목인 예시입니다:

<ListBox Name="lst" SelectionChanged="lst_SelectionChanged"
  CheckBox.Click="lst_SelectionChanged">
  <CheckBox Margin="3">옵션 1</CheckBox>
  <CheckBox Margin="3">옵션 2</CheckBox>
</ListBox>

ListBoxItem로 리스트 항목을 채우지 않은 경우, SelectedItem 값을 읽을 때 ListBoxItem 객체가 아닌, 리스트에 배치한 객체를 얻게 됩니다. 위 예제에서 SelectedItemCheckBox 객체를 제공합니다.

다음 코드는 현재 선택 항목을 가져오고,该项目이 선택되었는지 확인합니다.

private void lst_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (lst.SelectedItem == null) return;
    txtSelection.Text = String.Format(
      "당신이 선택한 항목 위치: {0}.\r\n체크 상태: {1}.",
      lst.SelectedIndex,
      ((CheckBox)lst.SelectedItem).IsChecked);
}

선택이 해제된 항목을 알아보고 싶다면, SelectionChangedEventArgs 객체의 RemovedItems 속성을 사용할 수 있습니다. 동일하게, AddedItems 속성은 선택된 항목을 알려줍니다. 단일 선택 모드에서는 선택 변경 시 항상 하나의 항목이 추가되고 하나의 항목이 제거됩니다. multiple 또는 extended 모드에서는 그렇지 않을 수 있습니다.

다음은 리스트 항목 집합을 순회하는 코드입니다:

private void cmd_ExamineAllItems(object sender, RoutedEventArgs e)
{
    var sb = new StringBuilder();
    foreach (CheckBox item in lst.Items)
    {
        if (item.IsChecked == true)
        {
            sb.Append(item.Content);
            sb.Append("은 체크되어 있습니다.");
            sb.Append("\r\n");
        }
    }
    txtSelection.Text = sb.ToString();
}

ListBoxItem에는 추가 기능인 IsSelected 속성, Selected 이벤트, Unselected 이벤트가 있습니다. 이러한 기능은 ListBoxSelectedItem 속성과 SelectionChanged 이벤트로도 구현할 수 있습니다.

재미있는 점은, 중첩된 객체 방법을 사용할 때 특정 개체의 ListBoxItem 래퍼를 얻는 기술입니다. 이 기술을 사용하는 코드는 첫 번째 항목이 리스트의 선택 항목인지 확인합니다:

var item = (ListBoxItem)lst.ContainerFromElement(
    (DependencyObject)lst.SelectedItems[0]);
MessageBox.Show("선택됨: " + item.IsSelected.ToString());

ComboBox

콤보 박스는 리스트 박스와 거의 동일한 방식으로 사용됩니다.

사용자가 콤보 박스에 텍스트를 입력하여 항목을 선택할 수 있도록 하려면, IsEditable 속성을 true로 설정해야 하며, 이미지 객체가 포함된 편집 가능한 콤보 박스를 채울 때는 ComboBoxItem 객체나 ToString() 표현이 의미 있는 객체를 사용해야 합니다. 예를 들어, 이미지 객체가 포함된 편집 가능한 콤보 박스를 채우면, 위쪽 부분에 Image 클래스의 전체 이름이 표시되며, 이는 매우 사용자 친화적이지 않습니다.

범위 기반 컨트롤

범위 기반 컨트롤의 기본 클래스는 RangeBase 클래스이며, 이는 Control 클래스에서 파생됩니다. RangeBase 클래스에는 다음과 같은 속성이 포함됩니다:

Value, Maximum, Minimum, SmallChange, LargeChange

ScrollView 컨트롤이 있기 때문에, ScrollBar는 거의 사용되지 않습니다. 이제 SliderProgressBar에 집중합니다.

Slider

188페이지 참조

ProgressBar

190페이지 참조

날짜 컨트롤

190페이지 참조.

태그: WPF UIElement ContentControl ButtonBase ItemsControl

7월 4일 17:45에 게시됨