컨트롤

WPF(Windows Presentation Foundation)는 Button, Label, TextBox, MenuListBox 같은 거의 모든 Windows 애플리케이션에서 사용되는 많은 공통 UI 구성 요소와 함께 제공됩니다. 지금까지 이러한 개체는 컨트롤이라고 불렀습니다. WPF SDK에서는 계속해서 “컨트롤”이라는 용어를 사용하여 애플리케이션에 표시되는 개체를 나타내는 모든 클래스를 대략적으로 지칭합니다. 그러나 클래스가 반드시 Control 클래스에서 상속을 받아야 표시되는 것은 아닙니다. Control 클래스에서 상속된 클래스에는 ControlTemplate이 포함되어 있습니다. 따라서 컨트롤 소비자는 새 서브클래스를 만들지 않아도 컨트롤의 모양을 대폭 변경할 수 있습니다. 이 항목에서는 컨트롤(Control 클래스에서 상속받는 컨트롤과 상속받지 않는 컨트롤)이 WPF에서 일반적으로 사용되는 방법에 관해 설명합니다.

컨트롤의 인스턴스 만들기

XAML(Extensible Application Markup Language) 또는 코드를 사용하여 애플리케이션에 컨트롤을 추가할 수 있습니다. 다음 예제에서는 사용자에게 이름과 성을 묻는 간단한 애플리케이션을 만드는 방법을 보여 줍니다. 이 예제에서는 XAML에서 컨트롤 6개, 즉 레이블 2개, 텍스트 상자 2개, 단추 2개를 만듭니다. 모든 컨트롤을 유사하게 만들 수 있습니다.

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="30"/>
    <RowDefinition Height="30"/>
    <RowDefinition Height="30"/>
    <RowDefinition/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition/>
    <ColumnDefinition/>
  </Grid.ColumnDefinitions>

  <Label>
    Enter your first name:
  </Label>
  <TextBox Grid.Row="0" Grid.Column="1" 
           Name="firstName" Margin="0,5,10,5"/>

  <Label Grid.Row="1" >
    Enter your last name:
  </Label>
  <TextBox Grid.Row="1" Grid.Column="1" 
           Name="lastName" Margin="0,5,10,5"/>

  <Button Grid.Row="2" Grid.Column="0" 
          Name="submit" Margin="2">
    View message
  </Button>

  <Button Grid.Row="2" Grid.Column="1" 
          Name="Clear" Margin="2">
    Clear Name
  </Button>
</Grid>

다음 예제에서는 코드로 동일한 애플리케이션을 만듭니다. 간략한 설명을 위해 Grid(grid1)를 만드는 과정은 샘플에서 제외되었습니다. grid1은 앞의 XAML 예제와 동일한 열과 행의 정의를 사용합니다.

Label firstNameLabel;
Label lastNameLabel;
TextBox firstName;
TextBox lastName;
Button submit;
Button clear;

void CreateControls()
{
    firstNameLabel = new Label();
    firstNameLabel.Content = "Enter your first name:";
    grid1.Children.Add(firstNameLabel);

    firstName = new TextBox();
    firstName.Margin = new Thickness(0, 5, 10, 5);
    Grid.SetColumn(firstName, 1);
    grid1.Children.Add(firstName);

    lastNameLabel = new Label();
    lastNameLabel.Content = "Enter your last name:";
    Grid.SetRow(lastNameLabel, 1);
    grid1.Children.Add(lastNameLabel);

    lastName = new TextBox();
    lastName.Margin = new Thickness(0, 5, 10, 5);
    Grid.SetColumn(lastName, 1);
    Grid.SetRow(lastName, 1);
    grid1.Children.Add(lastName);

    submit = new Button();
    submit.Content = "View message";
    Grid.SetRow(submit, 2);
    grid1.Children.Add(submit);

    clear = new Button();
    clear.Content = "Clear Name";
    Grid.SetRow(clear, 2);
    Grid.SetColumn(clear, 1);
    grid1.Children.Add(clear);
}
Private firstNameLabel As Label
Private lastNameLabel As Label
Private firstName As TextBox
Private lastName As TextBox
Private submit As Button
Private clear As Button

Sub CreateControls()
    firstNameLabel = New Label()
    firstNameLabel.Content = "Enter your first name:"
    grid1.Children.Add(firstNameLabel)

    firstName = New TextBox()
    firstName.Margin = New Thickness(0, 5, 10, 5)
    Grid.SetColumn(firstName, 1)
    grid1.Children.Add(firstName)

    lastNameLabel = New Label()
    lastNameLabel.Content = "Enter your last name:"
    Grid.SetRow(lastNameLabel, 1)
    grid1.Children.Add(lastNameLabel)

    lastName = New TextBox()
    lastName.Margin = New Thickness(0, 5, 10, 5)
    Grid.SetColumn(lastName, 1)
    Grid.SetRow(lastName, 1)
    grid1.Children.Add(lastName)

    submit = New Button()
    submit.Content = "View message"
    Grid.SetRow(submit, 2)
    grid1.Children.Add(submit)

    clear = New Button()
    clear.Content = "Clear Name"
    Grid.SetRow(clear, 2)
    Grid.SetColumn(clear, 1)
    grid1.Children.Add(clear)


End Sub

컨트롤의 모양 변경

일반적으로 애플리케이션의 모양과 느낌에 맞게 컨트롤의 모양을 변경합니다. 수행하려는 작업에 따라 다음 중 하나를 수행하여 컨트롤의 모양을 변경할 수 있습니다.

  • 컨트롤의 속성 값을 변경합니다.

  • 컨트롤의 Style을 만듭니다.

  • 컨트롤의 새 ControlTemplate을 만듭니다.

컨트롤의 속성 값 변경

대부분의 컨트롤에는 ButtonBackground와 같이 컨트롤이 표시되는 방식을 변경할 수 있는 속성이 있습니다. XAML 및 코드 둘 다에서 값 속성을 설정할 수 있습니다. 다음 예제의 경우 XAML에서 ButtonBackground, FontSize, FontWeight 속성을 설정합니다.

<Button FontSize="14" FontWeight="Bold">
  <!--Set the Background property of the Button to
    a LinearGradientBrush.-->
  <Button.Background>
    <LinearGradientBrush StartPoint="0,0.5" 
                            EndPoint="1,0.5">
      <GradientStop Color="Green" Offset="0.0" />
      <GradientStop Color="White" Offset="0.9" />
    </LinearGradientBrush>

  </Button.Background>
  View message
</Button>

다음 예제에서는 코드로 동일한 속성을 설정합니다.

LinearGradientBrush buttonBrush = new LinearGradientBrush();
buttonBrush.StartPoint = new Point(0, 0.5);
buttonBrush.EndPoint = new Point(1, 0.5);
buttonBrush.GradientStops.Add(new GradientStop(Colors.Green, 0));
buttonBrush.GradientStops.Add(new GradientStop(Colors.White, 0.9));

submit.Background = buttonBrush;
submit.FontSize = 14;
submit.FontWeight = FontWeights.Bold;
Dim buttonBrush As New LinearGradientBrush()
buttonBrush.StartPoint = New Point(0, 0.5)
buttonBrush.EndPoint = New Point(1, 0.5)
buttonBrush.GradientStops.Add(New GradientStop(Colors.Green, 0))
buttonBrush.GradientStops.Add(New GradientStop(Colors.White, 0.9))

submit.Background = buttonBrush
submit.FontSize = 14
submit.FontWeight = FontWeights.Bold

컨트롤에 대한 스타일 만들기

WPF를 사용하면 애플리케이션의 각 인스턴스에 대한 속성을 설정하는 대신 Style을 만들어 여러 컨트롤의 모양을 대량으로 지정할 수 있습니다. 다음 예제에서는 애플리케이션의 각 Button에 적용되는 Style을 만듭니다. Style 정의는 대개 ResourceDictionary에서 FrameworkElementResources 속성과 같은 XAML에 정의합니다.

<Style TargetType="Button">
  <Setter Property="FontSize" Value="14"/>
  <Setter Property="FontWeight" Value="Bold"/>
  <Setter Property="Background">
    <Setter.Value>
      <LinearGradientBrush StartPoint="0,0.5" 
                              EndPoint="1,0.5">
        <GradientStop Color="Green" Offset="0.0" />
        <GradientStop Color="White" Offset="0.9" />
      </LinearGradientBrush>

    </Setter.Value>
  </Setter>
</Style>

스타일에 키를 할당하고 컨트롤의 Style 속성에서 해당 키를 지정하여 특정 형식의 특정 컨트롤에만 스타일을 적용할 수도 있습니다. 스타일에 대한 자세한 내용은 스타일 지정 및 템플릿을 참조하세요.

ControlTemplate 만들기

Style을 사용하면 한 번에 여러 컨트롤의 속성을 설정할 수 있지만 때로는 Style을 만들어서 수행할 수 있는 것 이상으로 Control의 모양을 사용자 지정하고 싶을 수도 있습니다. Control 클래스에서 상속을 받는 클래스에는 Control의 모양과 구조를 정의하는 ControlTemplate이 있습니다. ControlTemplate 속성은 public이므로 Control에 기본값과 다른 ControlTemplate을 지정할 수 있습니다. Control의 모양을 사용자 지정하기 위해 컨트롤에서 상속을 받는 대신 Control에 새 ControlTemplate을 지정할 수 있는 경우가 많습니다.

매우 흔히 사용되는 컨트롤인 Button의 경우를 예로 들어 보겠습니다. Button의 기본 동작은 사용자가 클릭할 때 애플리케이션이 특정 작업을 수행할 수 있게 하는 것입니다. 기본적으로 WPF에서 Button은 볼록한 사각형으로 표시됩니다. 애플리케이션을 개발하면서 단추의 클릭 이벤트를 처리하여 Button의 동작을 활용할 수도 있지만, 단추 속성을 변경하여 수행할 수 있는 것 이상으로 단추의 모양을 변경하는 경우도 있습니다. 이러한 경우 새 ControlTemplate을 만들 수 있습니다.

다음 예제는 ControlTemplate 에 대 한는 Button합니다. ControlTemplate은 모서리가 둥글고 배경이 그라데이션 처리된 Button를 만듭니다. ControlTemplate에 포함되어 있는 BorderBackgroundGradientStop 개체 두 개가 들어 있는 LinearGradientBrush입니다. 첫 번째 GradientStop은 데이터 바인딩을 사용하여 GradientStopColor 속성을 단추 배경의 색에 바인딩합니다. ButtonBackground 속성을 설정할 때는 해당 값의 색이 첫 번째 GradientStop으로 사용됩니다. 데이터 바인딩에 대한 자세한 내용은 데이터 바인딩 개요를 참조하세요. 이 예제에서는 IsPressedtrue일 때 Button의 모양을 변경하는 Trigger도 만듭니다.

<!--Define a template that creates a gradient-colored button.-->
<Style TargetType="Button">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Border 
          x:Name="Border"  
          CornerRadius="20" 
          BorderThickness="1"
          BorderBrush="Black">
          <Border.Background>
            <LinearGradientBrush StartPoint="0,0.5" 
                                 EndPoint="1,0.5">
              <GradientStop Color="{Binding Background.Color, 
                    RelativeSource={RelativeSource TemplatedParent}}" 
                            Offset="0.0" />
              <GradientStop Color="White" Offset="0.9" />
            </LinearGradientBrush>
          </Border.Background>
          <ContentPresenter 
            Margin="2"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            RecognizesAccessKey="True"/>
        </Border>
        <ControlTemplate.Triggers>
          <!--Change the appearance of
          the button when the user clicks it.-->
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background">
              <Setter.Value>
                <LinearGradientBrush StartPoint="0,0.5" 
                                     EndPoint="1,0.5">
                  <GradientStop Color="{Binding Background.Color, 
                    RelativeSource={RelativeSource TemplatedParent}}" 
                                Offset="0.0" />
                  <GradientStop Color="DarkSlateGray" Offset="0.9" />
                </LinearGradientBrush>
              </Setter.Value>
            </Setter>
          </Trigger>

        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName"
        Background="Green">View message</Button>

참고

ButtonBackground 속성을 SolidColorBrush로 설정해야 예제가 정상적으로 작동합니다.

이벤트 구독

XAML 또는 코드를 사용하여 컨트롤의 이벤트를 구독할 수 있지만 코드로만 이벤트를 처리할 수 있습니다. 다음 예제에서는 ButtonClick 이벤트를 구독하는 방법을 보여 줍니다.

<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName" Click="submit_Click"
  Background="Green">View message</Button>
submit.Click += new RoutedEventHandler(submit_Click);
AddHandler submit.Click, AddressOf submit_Click

다음 예제에서는 ButtonClick 이벤트를 처리합니다.

void submit_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text);
}
Private Sub submit_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text)

End Sub

컨트롤의 풍부한 콘텐츠

Control 클래스에서 상속받는 대부분의 클래스는 서식 있는 콘텐츠를 포함할 수 있습니다. 예를 들어 Label은 문자열, Image 또는 Panel과 같은 개체를 포함할 수 있습니다. 다음 클래스는 풍부한 콘텐츠를 지원하고 WPF에서 대부분의 컨트롤에 대한 기본 클래스로 작동합니다.

이러한 기본 클래스에 대한 자세한 내용은 WPF 콘텐츠 모델을 참조하세요.

참고 항목