ControlTemplate을 만들어 기존 컨트롤의 모양 사용자 지정Customizing the Appearance of an Existing Control by Creating a ControlTemplate

컨트롤의 시각적 구조와 시각적 동작을 지정 하 ControlTemplate입니다.A ControlTemplate specifies the visual structure and visual behavior of a control. ControlTemplate을 제공 하 여 컨트롤의 모양을 사용자 지정할 수 있습니다.You can customize the appearance of a control by giving it a new ControlTemplate. ControlTemplate를 만들 때 해당 기능을 변경 하지 않고 기존 컨트롤의 모양을 바꿉니다.When you create a ControlTemplate, you replace the appearance of an existing control without changing its functionality. 예를 들어, 기본 정사각형 셰이프 대신 응용 프로그램의 둥근 모양 단추를 만들 수 있지만 단추는 계속 해 서 Click 이벤트를 발생 시킵니다.For example, you can make the buttons in your application round instead of the default square shape, but the button will still raise the Click event.

이 항목에서는 ControlTemplate의 다양 한 부분에 대해 설명 하 고 Button에 대 한 간단한 ControlTemplate을 만드는 방법을 보여 주고 컨트롤의 컨트롤 계약을 이해 하는 방법을 설명 합니다. 그러면 컨트롤의 모양을 사용자 지정할 수 있습니다.This topic explains the various parts of a ControlTemplate, demonstrates creating a simple ControlTemplate for a Button, and explains how to understand the control contract of a control so that you can customize its appearance. XAMLXAML에서 ControlTemplate를 만들기 때문에 코드를 작성 하지 않고 컨트롤의 모양을 변경할 수 있습니다.Because you create a ControlTemplate in XAMLXAML, you can change a control's appearance without writing any code. Blend for Visual Studio와 같은 디자이너를 사용 하 여 사용자 지정 컨트롤 템플릿을 만들 수도 있습니다.You can also use a designer, such as Blend for Visual Studio, to create custom control templates. 이 항목에서는 Button의 모양을 사용자 지정 하 고 항목의 끝에 있는 전체 예제를 나열 하는 XAMLXAML 예제를 보여 줍니다.This topic shows examples in the XAMLXAML that customize the appearance of a Button and lists the complete example at the end of the topic. Blend for Visual Studio를 사용 하는 방법에 대 한 자세한 내용은 템플릿을 지 원하는 컨트롤의 스타일지정을 참조 하세요.For more information about using Blend for Visual Studio, see Styling a control that supports templates.

다음 그림에서는이 항목에서 만든 ControlTemplate를 사용 하는 Button 보여 줍니다.The following illustrations show a Button that uses the ControlTemplate that is created in this topic.

사용자 지정 컨트롤 템플릿을 사용하는 단추A button with a custom control template. 사용자 지정 컨트롤 템플릿을 사용하는 단추A button that uses a custom control template

빨간색 테두리가 있는 단추A button with a red border. 사용자 지정 컨트롤 템플릿을 사용하고 마우스 포인터가 위에 놓여 있는 단추A button that uses a custom control template and has the mouse pointer over it

PrerequisitesPrerequisites

이 항목에서는 컨트롤에 설명된 대로 컨트롤과 스타일을 만들고 사용하는 방법을 알고 있다고 가정합니다.This topic assumes that you understand how to create and use controls and styles as discussed in Controls. 이 항목에서 설명 하는 개념은 UserControl를 제외 하 고 Control 클래스에서 상속 되는 요소에 적용 됩니다.The concepts discussed in this topic apply to elements that inherit from the Control class, except for the UserControl. UserControlControlTemplate을 적용할 수 없습니다.You cannot apply a ControlTemplate to a UserControl.

ControlTemplate을 만들어야 하는 경우When You Should Create a ControlTemplate

컨트롤에는 Background, ForegroundFontFamily와 같이 컨트롤의 모양에 대 한 다양 한 측면을 지정 하기 위해 설정할 수 있는 다양 한 속성이 있지만 이러한 속성을 설정 하 여 변경할 수 있는 내용은 제한 됩니다.Controls have many properties, such as Background, Foreground, and FontFamily, that you can set to specify different aspects of the control's appearance, but the changes that you can make by setting these properties are limited. 예를 들어 CheckBox에서 Foreground 속성을 blue로 설정 하 고 FontStyle을 기울임꼴로 설정할 수 있습니다.For example, you can set the Foreground property to blue and FontStyle to italic on a CheckBox.

컨트롤에 대 한 새 ControlTemplate을 만들 수 없는 경우에는 모든 WPFWPF기반 응용 프로그램의 모든 컨트롤에 동일한 일반 모양이 지정 되어 사용자 지정 모양과 느낌을 가진 응용 프로그램을 만드는 기능이 제한 됩니다.Without the ability to create a new ControlTemplate for controls, all controls in every WPFWPF-based application would have the same general appearance, which would limit the ability to create an application with a custom look and feel. 기본적으로 모든 CheckBox에는 유사한 특징이 있습니다.By default, every CheckBox has similar characteristics. 예를 들어 CheckBox의 내용은 항상 선택 표시기의 오른쪽에 있고 확인 표시는 항상 CheckBox 선택 됨을 나타내는 데 사용 됩니다.For example, the content of the CheckBox is always to the right of the selection indicator, and the check mark is always used to indicate that the CheckBox is selected.

컨트롤의 다른 속성이 수행 하는 설정에 따라 컨트롤의 모양을 사용자 지정 하려는 경우 ControlTemplate를 만듭니다.You create a ControlTemplate when you want to customize the control's appearance beyond what setting the other properties on the control will do. CheckBox예제에서는 확인란의 내용이 선택 표시기 위에 표시 되도록 하 고 X를 클릭 하 여 CheckBox 선택 되었음을 나타냅니다.In the example of the CheckBox, suppose that you want the content of the check box to be above the selection indicator and you want an X to indicate that the CheckBox is selected. 이러한 변경 내용은 CheckBoxControlTemplate에서 지정 합니다.You specify these changes in the ControlTemplate of the CheckBox.

다음 그림에서는 기본 ControlTemplate를 사용 하는 CheckBox 보여 줍니다.The following illustration shows a CheckBox that uses a default ControlTemplate.

기본 컨트롤 템플릿을 사용하는 확인란A checkbox with the default control template. 기본 컨트롤 템플릿을 사용하는 확인란A CheckBox that uses the default control template

다음 그림에서는 사용자 지정 ControlTemplate를 사용 하 여 CheckBox 콘텐츠를 선택 표시기 위에 놓고 CheckBox를 선택 하면 X를 표시 하는 CheckBox 보여 줍니다.The following illustration shows a CheckBox that uses a custom ControlTemplate to place the content of the CheckBox above the selection indicator and displays an X when the CheckBox is selected.

사용자 지정 컨트롤 템플릿을 사용하는 확인란A checkbox with a custom control template. 사용자 지정 컨트롤 템플릿을 사용하는 확인란A CheckBox that uses a custom control template

이 샘플의 CheckBox에 대 한 ControlTemplate 비교적 복잡 하므로이 항목에서는 Button에 대 한 ControlTemplate를 만드는 간단한 예제를 사용 합니다.The ControlTemplate for the CheckBox in this sample is relatively complex, so this topic uses a simpler example of creating a ControlTemplate for a Button.

컨트롤의 시각적 구조 변경Changing the Visual Structure of a Control

WPFWPF에서 컨트롤은 종종 복합 FrameworkElement 개체입니다.In WPFWPF, a control is often a composite FrameworkElement objects. ControlTemplate를 만드는 경우 FrameworkElement 개체를 결합 하 여 단일 컨트롤을 빌드합니다.When you create a ControlTemplate, you combine FrameworkElement objects to build a single control. ControlTemplate에는 루트 요소로 FrameworkElement 하나만 있어야 합니다.A ControlTemplate must have only one FrameworkElement as its root element. 일반적으로 루트 요소는 다른 FrameworkElement 개체를 포함 합니다.The root element usually contains other FrameworkElement objects. 개체가 조합되면 컨트롤의 시각적 구조가 만들어집니다.The combination of objects makes up the control's visual structure.

다음 예에서는 Button에 대 한 사용자 지정 ControlTemplate를 만듭니다.The following example creates a custom ControlTemplate for the Button. ControlTemplate Button의 시각적 구조를 만듭니다.The ControlTemplate creates the visual structure of the Button. 이 예제에서는 마우스 포인트를 단추 위로 이동하거나 단추를 클릭할 때 단추의 모양이 변경되지 않습니다.This example does not change the button's appearance when you move the mouse pointer over it or click it. 단추가 다른 상태에 있을 때 단추의 모양을 변경하는 방법에 대해서는 이 항목의 뒷부분에서 설명합니다.Changing the button's appearance when it is in a different state is discussed later in this topic.

이 예제에서 시각적 구조는 다음 부분으로 구성되어 있습니다.In this example, the visual structure consists of the following parts:

<ControlTemplate TargetType="Button">
  <Border Name="RootElement">

    <!--Create the SolidColorBrush for the Background 
        as an object elemment and give it a name so 
        it can be referred to elsewhere in the
        control template.-->
    <Border.Background>
      <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
    </Border.Background>

    <!--Create a border that has a different color
        by adding smaller grid. The background of 
        this grid is specificied by the button's 
        Background property.-->
    <Grid Margin="4" Background="{TemplateBinding Background}">

      <!--Use a ContentPresenter to display the Content of
          the Button.-->
      <ContentPresenter
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
        Margin="4,5,4,4" />
    </Grid>

  </Border>
</ControlTemplate>

TemplateBinding을 사용하여 컨트롤의 속성 기능 유지Preserving the Functionality of a Control's Properties by Using TemplateBinding

ControlTemplate을 만드는 경우에도 공용 속성을 사용 하 여 컨트롤의 모양을 변경 하는 것이 좋습니다.When you create a new ControlTemplate, you still might want to use the public properties to change the control's appearance. TemplateBinding 태그 확장은 ControlTemplate에 있는 요소의 속성을 컨트롤에 정의 된 공용 속성에 바인딩합니다.The TemplateBinding markup extension binds a property of an element that is in the ControlTemplate to a public property that is defined by the control. TemplateBinding을 사용하면 컨트롤의 속성이 템플릿의 매개 변수로 작동됩니다.When you use TemplateBinding, you enable properties on the control to act as parameters to the template. 즉, 컨트롤의 속성을 설정하면 해당 값은 TemplateBinding이 있는 요소로 전달됩니다.That is, when a property on a control is set, that value is passed on to the element that has the TemplateBinding on it.

다음 예제에서는 TemplateBinding 태그 확장을 사용 하 여 ControlTemplate에 있는 요소의 속성을 단추에 정의 된 공용 속성에 바인딩하는 위의 예제 부분을 반복 합니다.The following example repeats the part of the preceding example that uses the TemplateBinding markup extension to bind properties of elements that are in the ControlTemplate to public properties that are defined by the button.

<Grid Margin="4" Background="{TemplateBinding Background}">

  <!--Use a ContentPresenter to display the Content of
      the Button.-->
  <ContentPresenter
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Margin="4,5,4,4" />
</Grid>

이 예제에서는 Grid Panel.Background 속성 템플릿이 Control.Background에 바인딩되어 있습니다.In this example, the Grid has its Panel.Background property template bound to Control.Background. Panel.Background는 템플릿 바인딩 이기 때문에 동일한 ControlTemplate를 사용 하는 여러 단추를 만든 다음 Control.Background를 각 단추의 다른 값으로 설정할 수 있습니다.Because Panel.Background is template bound, you can create multiple buttons that use the same ControlTemplate and set the Control.Background to different values on each button. Control.Background ControlTemplate요소의 속성에 매핑되지 않은 경우 단추의 Control.Background를 설정 해도 단추의 모양에는 영향을 주지 않습니다.If Control.Background was not template bound to a property of an element in the ControlTemplate, setting the Control.Background of a button would have no impact on the button's appearance.

두 속성의 이름이 같지 않아도 됩니다.Note that the names of the two properties do not need to be identical. 앞의 예제에서 ButtonControl.HorizontalContentAlignment 속성은 ContentPresenterFrameworkElement.HorizontalAlignment 속성에 바인딩되는 템플릿입니다.In the preceding example, the Control.HorizontalContentAlignment property of the Button is template bound to the FrameworkElement.HorizontalAlignment property of the ContentPresenter. 이를 통해 단추 콘텐츠의 가로 위치를 지정할 수 있습니다.This enables the content of the button to be positioned horizontally. ContentPresenterHorizontalContentAlignment라는 속성이 없지만 Control.HorizontalContentAlignment FrameworkElement.HorizontalAlignment바인딩할 수 있습니다.ContentPresenter does not have a property named HorizontalContentAlignment, but Control.HorizontalContentAlignment can be bound to FrameworkElement.HorizontalAlignment. 속성을 템플릿 바인딩할 경우 대상 속성과 소스 속성의 형식이 동일해야 합니다.When you template bind a property, be sure that the target and source properties are the same type.

Control 클래스는 컨트롤이 설정 될 때 컨트롤에 영향을 주는 데 사용 해야 하는 여러 속성을 정의 합니다.The Control class defines several properties that must be used by the control template to have an effect on the control when they are set. 속성을 사용 하는 ControlTemplate는 속성에 따라 달라 집니다.How the ControlTemplate uses the property depends on the property. ControlTemplate는 다음 방법 중 하나를 사용 하 여 속성을 사용 해야 합니다.The ControlTemplate must use the property in one of the following ways:

다음 표에서는 Control 클래스에서 컨트롤에 상속 된 시각적 속성을 보여 줍니다.The following table lists the visual properties inherited by a control from the Control class. 또한 컨트롤의 기본 컨트롤 템플릿이 상속받은 속성 값을 사용하는지 또는 템플릿 바인딩되어야 하는지를 나타냅니다.It also indicates whether the default control template of a control uses the inherited property value or if it must be template bound.

속성Property 사용 방법Usage method
Background 템플릿 바인딩Template binding
BorderThickness 템플릿 바인딩Template binding
BorderBrush 템플릿 바인딩Template binding
FontFamily 속성 상속 또는 템플릿 바인딩Property inheritance or template binding
FontSize 속성 상속 또는 템플릿 바인딩Property inheritance or template binding
FontStretch 속성 상속 또는 템플릿 바인딩Property inheritance or template binding
FontWeight 속성 상속 또는 템플릿 바인딩Property inheritance or template binding
Foreground 속성 상속 또는 템플릿 바인딩Property inheritance or template binding
HorizontalContentAlignment 템플릿 바인딩Template binding
Padding 템플릿 바인딩Template binding
VerticalContentAlignment 템플릿 바인딩Template binding

테이블에는 Control 클래스에서 상속 된 시각적 속성만 나열 됩니다.The table lists only the visual properties inherited from the Control class. 표에 나열 된 속성 외에도 컨트롤은 부모 프레임 워크 요소에서 DataContext, LanguageTextDecorations 속성을 상속할 수 있습니다.Apart from the properties listed in the table, a control may also inherit the DataContext, Language, and TextDecorations properties from the parent framework element.

또한 ContentPresenter ContentControlControlTemplate에 있는 경우 ContentPresenter ContentTemplateContent 속성에 자동으로 바인딩됩니다.Also, if the ContentPresenter is in the ControlTemplate of a ContentControl, the ContentPresenter will automatically bind to the ContentTemplate and Content properties. 마찬가지로 ItemsControlControlTemplate에 있는 ItemsPresenter은 자동으로 ItemsItemsPresenter 속성에 바인딩됩니다.Likewise, an ItemsPresenter that is in the ControlTemplate of an ItemsControl will automatically bind to the Items and ItemsPresenter properties.

다음 예제에서는 앞의 예제에 정의 된 ControlTemplate를 사용 하는 두 개의 단추를 만듭니다.The following example creates two buttons that use the ControlTemplate defined in the preceding example. 이 예에서는 각 단추에 Background, ForegroundFontSize 속성을 설정 합니다.The example sets the Background, Foreground, and FontSize properties on each button. Background 속성을 설정 하는 것은 ControlTemplate에 템플릿이 바인딩되어 있으므로 효과가 있습니다.Setting the Background property has an effect because it is template bound in the ControlTemplate. ForegroundFontSize 속성이 템플릿 바운드가 아닌 경우에도 해당 값이 상속 되므로 값을 설정 하면 효과가 있습니다.Even though the Foreground and FontSize properties are not template bound, setting them has an effect because their values are inherited.

<StackPanel>
  <Button Style="{StaticResource newTemplate}" 
          Background="Navy" Foreground="White" FontSize="14"
          Content="Button1"/>

  <Button Style="{StaticResource newTemplate}" 
          Background="Purple" Foreground="White" FontSize="14"
          Content="Button2" HorizontalContentAlignment="Left"/>
</StackPanel>

앞의 예제에서는 다음 그림과 유사한 출력을 생성합니다.The preceding example produces output that is similar to the following illustration.

단추 두 개: 파란색 단추 하나와 자주색 단추 하나Two buttons, one blue and one purple. 배경색이 서로 다른 두 개의 단추Two buttons with different background colors

상태에 따라 컨트롤의 모양 변경Changing the Appearance of a Control Depending on Its State

기본 모양을 가진 단추와 앞의 예제에서 사용된 단추의 차이점은 기본 단추가 다른 상태에 있을 때 약간 변경된다는 것입니다.The difference between a button with its default appearance and the button in the preceding example is that the default button subtly changes when it is in different states. 예를 들어 단추를 누르거나 마우스 포인터가 단추 위에 있으면 기본 단추의 모양이 변경됩니다.For example, the default button's appearance changes when the button is pressed, or when the mouse pointer is over the button. ControlTemplate는 컨트롤의 기능을 변경 하지 않지만 컨트롤의 시각적 동작을 변경 합니다.Although the ControlTemplate does not change the functionality of a control, it does change the control's visual behavior. 시각적 동작은 컨트롤이 특정 상태에 있을 때의 컨트롤 모양을 설명합니다.A visual behavior describes the control appearance when it is in a certain state. 컨트롤의 기능과 시각적 동작의 차이점을 파악하려면 단추 예제를 참조하세요.To understand the difference between the functionality and visual behavior of a control, consider the button example. 단추의 기능은 클릭 될 때 Click 이벤트를 발생 시키는 것 이지만 단추의 시각적 동작은 포인터가 가리키거나 눌린 상태에서 모양을 변경 하는 것입니다.The button's functionality is to raise the Click event when it is clicked, but the button's visual behavior is to change its appearance when it is pointed to or pressed.

VisualState 개체를 사용 하 여 컨트롤이 특정 상태에 있을 때 컨트롤의 모양을 지정할 수 있습니다.You use VisualState objects to specify the appearance of a control when it is in a certain state. VisualState에는 ControlTemplate에 있는 요소의 모양을 변경 하는 Storyboard 포함 되어 있습니다.A VisualState contains a Storyboard that changes the appearance of the elements that are in the ControlTemplate. 컨트롤의 논리가 VisualStateManager를 사용 하 여 상태를 변경 하기 때문에이 작업을 수행 하기 위해 코드를 작성할 필요가 없습니다.You do not have to write any code to make this occur because the control's logic changes state by using the VisualStateManager. 컨트롤이 VisualState.Name 속성으로 지정 된 상태에 들어가면 Storyboard 시작 됩니다.When the control enters the state that is specified by the VisualState.Name property, the Storyboard begins. 컨트롤이 상태를 종료 하면 Storyboard 중지 됩니다.When the control exits the state, the Storyboard stops.

다음 예제에서는 마우스 포인터가 위에 있을 때 Button 모양을 변경 하는 VisualState 보여 줍니다.The following example shows the VisualState that changes the appearance of a Button when the mouse pointer is over it. Storyboard BorderBrush색을 변경 하 여 단추의 테두리 색을 변경 합니다.The Storyboard changes the button's border color by changing the color of the BorderBrush. 이 항목의 시작 부분에 ControlTemplate 예제를 참조 하는 경우 BorderBrushBorderBackground에 할당 된 SolidColorBrush 이름 이라고 기억 하십시오.If you refer to the ControlTemplate example at the beginning of this topic, you will recall that BorderBrush is the name of the SolidColorBrush that is assigned to the Background of the Border.

<!--Change the border of the button to red when the
    mouse is over the button.-->
<VisualState x:Name="MouseOver">
  <Storyboard>
    <ColorAnimation Storyboard.TargetName="BorderBrush"     
                    Storyboard.TargetProperty="Color"
                    To="Red" />

  </Storyboard>
</VisualState>

이 컨트롤을 통해 해당 컨트롤 계약의 일부로 상태를 정의합니다. 컨트롤 계약에 대해서는 이 항목의 뒷부분에 있는 컨트롤 계약을 이해하여 다른 컨트롤 사용자 지정에서 자세히 설명합니다.The control is responsible for defining the states as part of its control contract, which is discussed in detail in Customizing Other Controls by Understanding the Control Contract later in this topic. 다음 표에서는 Button에 대해 지정 된 상태를 나열 합니다.The following table lists the states that are specified for the Button.

VisualState 이름VisualState Name VisualStateGroup 이름VisualStateGroup Name 설명Description
보통Normal CommonStatesCommonStates 기본 상태입니다.The default state.
MouseOverMouseOver CommonStatesCommonStates 마우스 포인터가 컨트롤 위에 있습니다.The mouse pointer is positioned over the control.
누름Pressed CommonStatesCommonStates 컨트롤을 눌렀습니다.The control is pressed.
DisabledDisabled CommonStatesCommonStates 컨트롤이 비활성화되었습니다.The control is disabled.
포커스 있음Focused FocusStatesFocusStates 컨트롤에 포커스가 있습니다.The control has focus.
포커스 없음Unfocused FocusStatesFocusStates 컨트롤에 포커스가 없습니다.The control does not have focus.

Button는 두 개의 상태 그룹을 정의 합니다. CommonStates 그룹에는 Normal, MouseOver, PressedDisabled 상태가 포함 됩니다.The Button defines two state groups: the CommonStates group contains the Normal, MouseOver, Pressed, and Disabled states. FocusStates 그룹에는 FocusedUnfocused 상태가 포함됩니다.The FocusStates group contains the Focused and Unfocused states. 같은 상태 그룹에 있는 상태는 함께 사용할 수 없습니다.States in the same state group are mutually exclusive. 컨트롤은 항상 그룹마다 한 개의 상태에 있습니다.The control is always in exactly one state per group. 예를 들어 Button는 마우스 포인터가 위에 있지 않아도 포커스를 가질 수 있으므로 Focused 상태의 Button MouseOver, Pressed또는 Normal 상태일 수 있습니다.For example, a Button can have focus even when the mouse pointer is not over it, so a Button in the Focused state can be in the MouseOver, Pressed, or Normal state.

VisualStateGroup 개체에 VisualState 개체를 추가 합니다.You add VisualState objects to VisualStateGroup objects. 연결 된 VisualStateGroups 속성에 VisualStateGroup 개체를 추가 합니다.You add VisualStateGroup objects to the VisualStateGroups attached property. 다음 예제에서는 Normal, MouseOverPressed 상태에 대 한 VisualState 개체를 정의 합니다 .이 개체는 모두 CommonStates 그룹에 있습니다.The following example defines the VisualState objects for the Normal, MouseOver, and Pressed states, which are all in the CommonStates group. VisualStateName은 위의 테이블에 있는 이름과 일치 합니다.The Name of each VisualState matches the name in the preceding table. 간단한 예제를 제공하기 위해 Disabled 상태와 FocusStates 그룹의 상태는 생략되었지만 이 항목의 끝에 있는 전체 예제에는 포함되어 있습니다.The Disabled state and the states in the FocusStates group are omitted to keep the example short, but they are included in the entire example at the end of this topic.

참고

ControlTemplate의 루트 FrameworkElement에 연결 된 VisualStateGroups 속성을 설정 해야 합니다.Be sure to set the VisualStateGroups attached property on the root FrameworkElement of the ControlTemplate.

<ControlTemplate TargetType="Button">
  <Border Name="RootElement">

    <VisualStateManager.VisualStateGroups>

      <!--Define the states and transitions for the common states.
          The states in the VisualStateGroup are mutually exclusive to
          each other.-->
      <VisualStateGroup x:Name="CommonStates">

        <!--The Normal state is the state the button is in
            when it is not in another state from this VisualStateGroup.-->
        <VisualState x:Name="Normal" />

        <!--Change the SolidColorBrush, BorderBrush, to red when the
            mouse is over the button.-->
        <VisualState x:Name="MouseOver">
          <Storyboard>
            <ColorAnimation Storyboard.TargetName="BorderBrush" 
                            Storyboard.TargetProperty="Color" 
                            To="Red" />
          </Storyboard>
        </VisualState>

        <!--Change the SolidColorBrush, BorderBrush, to Transparent when the
            button is pressed.-->
        <VisualState x:Name="Pressed">
          <Storyboard>
            <ColorAnimation Storyboard.TargetName="BorderBrush" 
                            Storyboard.TargetProperty="Color"
                            To="Transparent"/>
          </Storyboard>
        </VisualState>

        <!--The Disabled state is omitted for brevity.-->
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Border.Background>
      <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
    </Border.Background>

    <Grid Background="{TemplateBinding Background}" Margin="4">
      <ContentPresenter
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
        Margin="4,5,4,4" />
    </Grid>
  </Border>
</ControlTemplate>

앞의 예제에서는 다음 그림과 유사한 출력을 생성합니다.The preceding example produces output that is similar to the following illustrations.

사용자 지정 컨트롤 템플릿을 사용하는 단추A button with a custom control template. 정상 상태에서 사용자 지정 컨트롤 템플릿을 사용하는 단추A button that uses a custom control template in the normal state

빨간색 테두리가 있는 단추A button with a red border. 마우스가 위에 있는 상태에서 사용자 지정 컨트롤 템플릿을 사용하는 단추A button that uses a custom control template in the mouse over state

단추를 누르면 테두리가 투명해집니다.The border is transparent on a pressed button. 누름 상태에서 사용자 지정 컨트롤 템플릿을 사용하는 단추A button that uses a custom control template in the pressed state

WPFWPF와 함께 제공된 컨트롤의 시각적 상태를 찾으려면 Control 스타일 및 템플릿을 참조하세요.To find the visual states for controls that are included with WPFWPF, see Control Styles and Templates.

상태 간 전환 시 컨트롤의 동작 지정Specifying the Behavior of a Control When It Transitions Between States

위의 예제에서 단추를 클릭하면 모양도 변경되지만 단추를 1초 동안 누르고 있지 않으면 효과가 표시되지 않습니다.In the preceding example, the appearance of the button also changes when the user clicks it, but unless the button is pressed for a full second, the user does not see the effect. 기본적으로 애니메이션은 적용되려면 1초가 걸립니다.By default, the animation takes one second to occur. 사용자가 단추를 클릭 하 여 더 짧은 시간 안에 놓을 가능성이 있기 때문에 ControlTemplate를 기본 상태로 두면 시각적 피드백이 적용 되지 않습니다.Because users are likely to click and release a button in much less time, the visual feedback will not be effective if you leave the ControlTemplate in its default state.

ControlTemplateVisualTransition 개체를 추가 하 여 컨트롤을 한 상태에서 다른 상태로 원활 하 게 전환 하기 위해 애니메이션이 발생 하는 시간을 지정할 수 있습니다.You can specify the amount of time that it takes an animation to occur to smoothly transition a control from one state to another by adding VisualTransition objects to the ControlTemplate. 만들 때는 VisualTransition, 다음 중 하나 이상을 지정:When you create a VisualTransition, you specify one or more of the following:

  • 적용할 상태 간에 전환되는 데 소요되는 시간The time it takes for a transition between states to occur.

  • 컨트롤의 모양에 전환 시 적용되는 추가 변경 내용Additional changes in the control's appearance that occur at the time of the transition.

  • VisualTransition 적용 되는 상태입니다.Which states the VisualTransition is applied to.

전환 기간 지정Specifying the Duration of a Transition

전환 하는 걸리는 시간을 설정 하 여 지정할 수 있습니다는 GeneratedDuration 속성입니다.You can specify how long a transition takes by setting the GeneratedDuration property. 위의 예제에는 단추를 누를 때 단추의 테두리가 투명해 지는 것을 지정 하는 VisualState 있습니다. 그러나 단추를 빠르게 누르고 놓았을 경우 애니메이션을 눈에 띄는 시간이 오래 걸립니다.The preceding example has a VisualState that specifies that the button's border becomes transparent when the button is pressed, but the animation takes too long to be noticeable if the button is quickly pressed and released. VisualTransition를 사용 하 여 컨트롤을 눌린 상태로 전환 하는 데 소요 되는 시간을 지정할 수 있습니다.You can use a VisualTransition to specify the amount of time it takes the control to transition into the pressed state. 다음 예제에서는 컨트롤이 누른 상태로 전환되는 데 1/100초가 걸리도록 지정합니다.The following example specifies that the control takes one hundredth of a second to go into the pressed state.

<!--Take one hundredth of a second to transition to the
    Pressed state.-->
<VisualTransition To="Pressed" 
                  GeneratedDuration="0:0:0.01" />

전환 중 컨트롤의 모양 변경 지정Specifying Changes to the Control's Appearance During a Transition

VisualTransition에는 컨트롤이 상태 간에 전환 될 때 시작 하는 Storyboard 포함 되어 있습니다.The VisualTransition contains a Storyboard that begins when the control transitions between states. 예를 들어 컨트롤이 MouseOver 상태에서 Normal 상태로 전환될 때 특정 애니메이션이 적용되도록 지정할 수 있습니다.For example, you can specify that a certain animation occurs when the control transitions from the MouseOver state to the Normal State. 다음 예에서는 사용자가 마우스 포인터를 단추 밖으로 이동할 때 단추의 테두리가 파랑, 노란색, 1.5 초 내 검은색으로 변경 될 때이를 지정 하는 VisualTransition을 만듭니다.The following example creates a VisualTransition that specifies that when the user moves the mouse pointer away from the button, the button's border changes to blue, then to yellow, then to black in 1.5 seconds.

<!--Take one and a half seconds to transition from the
    MouseOver state to the Normal state. 
    Have the SolidColorBrush, BorderBrush, fade to blue, 
    then to yellow, and then to black in that time.-->
<VisualTransition From="MouseOver" To="Normal" 
                      GeneratedDuration="0:0:1.5">
  <Storyboard>
    <ColorAnimationUsingKeyFrames
      Storyboard.TargetProperty="Color"
      Storyboard.TargetName="BorderBrush"
      FillBehavior="HoldEnd" >

      <ColorAnimationUsingKeyFrames.KeyFrames>

        <LinearColorKeyFrame Value="Blue" 
          KeyTime="0:0:0.5" />
        <LinearColorKeyFrame Value="Yellow" 
          KeyTime="0:0:1" />
        <LinearColorKeyFrame Value="Black" 
          KeyTime="0:0:1.5" />

      </ColorAnimationUsingKeyFrames.KeyFrames>
    </ColorAnimationUsingKeyFrames>
  </Storyboard>
</VisualTransition>

VisualTransition 적용 시기 지정Specifying When a VisualTransition Is Applied

VisualTransition는 특정 상태에만 적용 되도록 제한 하거나, 컨트롤이 상태 간에 전환 될 때마다 적용 될 수 있습니다.A VisualTransition can be restricted to apply to only certain states, or it can be applied any time the control transitions between states. 위의 예제에서는 컨트롤이 MouseOver 상태에서 Normal 상태로 이동할 때 VisualTransition 적용 됩니다. 이전 예제에서는 컨트롤이 Pressed 상태로 전환 될 때 VisualTransition 적용 됩니다.In the preceding example, the VisualTransition is applied when the control goes from the MouseOver state to the Normal state; in the example before that, the VisualTransition is applied when the control goes into the Pressed state. 시간을 제한할 수는 VisualTransition 설정 하 여 적용 되는 ToFrom 속성.You restrict when a VisualTransition is applied by setting the To and From properties. 다음 표에서는 최대한의 제한에서 최소한의 제한까지 제한 수준에 대해 설명합니다.The following table describes the levels of restriction from most restrictive to least restrictive.

제한 유형Type of restriction From 값Value of From To 값Value of To
지정된 상태에서 지정된 다른 상태로 전환From a specified state to another specified state 이름을 VisualStateThe name of a VisualState 이름을 VisualStateThe name of a VisualState
임의의 상태에서 지정된 상태로 전환From any state to a specified state 설정 안 함Not set 이름을 VisualStateThe name of a VisualState
지정된 상태에서 임의의 상태로 전환From a specified state to any state 이름을 VisualStateThe name of a VisualState 설정 안 함Not set
임의의 상태에서 임의의 다른 상태로 전환From any state to any other state 설정 안 함Not set 설정 안 함Not set

여러 개 있을 수 있습니다 VisualTransition 개체는 VisualStateGroup 동일한 상태를 참조 하는 있지만 이러한 이전 표에 지정 된 순서 대로 사용 됩니다.You can have multiple VisualTransition objects in a VisualStateGroup that refer to the same state, but they will be used in the order that the previous table specifies. 다음 예제에는 두 개의 VisualTransition 개체가 있습니다.In the following example, there are two VisualTransition objects. 컨트롤에서 전환 하는 경우는 Pressed 상태는 MouseOver 상태를 VisualTransition 둘 다를 포함 하는 FromTo 집합이 사용 됩니다.When the control transitions from the Pressed state to the MouseOver state, the VisualTransition that has both From and To set is used. 컨트롤이 Pressed가 아닌 상태에서 MouseOver 상태로 전환될 때는 다른 상태가 사용됩니다.When the control transitions from a state that is not Pressed to the MouseOver state, the other state is used.

<!--Take one half second to trasition to the MouseOver state.-->
<VisualTransition To="MouseOver" 
                  GeneratedDuration="0:0:0.5" />

<!--Take one hundredth of a second to transition from the
    Pressed state to the MouseOver state.-->
<VisualTransition From="Pressed" To="MouseOver" 
                  GeneratedDuration="0:0:0.01" />

VisualStateGroup에는 VisualStateGroupVisualState 개체에 적용 되는 VisualTransition 개체를 포함 하는 Transitions 속성이 있습니다.The VisualStateGroup has a Transitions property that contains the VisualTransition objects that apply to the VisualState objects in the VisualStateGroup. ControlTemplate 저자는 원하는 VisualTransition를 자유롭게 포함할 수 있습니다.As the ControlTemplate author, you are free to include any VisualTransition you want. 그러나 ToFrom 속성이 VisualStateGroup에 없는 상태 이름으로 설정 된 경우 VisualTransition는 무시 됩니다.However, if the To and From properties are set to state names that are not in the VisualStateGroup, the VisualTransition is ignored.

다음 예에서는 CommonStates에 대 한 VisualStateGroup를 보여 줍니다.The following example shows the VisualStateGroup for the CommonStates. 이 예제에서는 단추의 다음 전환에 대 한 VisualTransition를 정의 합니다.The example defines a VisualTransition for each of the button's following transitions.

  • Pressed 상태로 전환To the Pressed state.

  • MouseOver 상태로 전환To the MouseOver state.

  • Pressed 상태에서 MouseOver 상태로 전환From the Pressed state to the MouseOver state.

  • MouseOver 상태에서 Normal 상태로 전환From the MouseOver state to the Normal state.

<VisualStateGroup x:Name="CommonStates">

  <!--Define the VisualTransitions that
      can be used when the control transitions 
      between VisualStates that are defined in the
      VisualStatGroup.-->
  <VisualStateGroup.Transitions>

    <!--Take one hundredth of a second to 
        transition to the Pressed state.-->
    <VisualTransition To="Pressed" 
                      GeneratedDuration="0:0:0.01" />

    <!--Take one half second to trasition 
        to the MouseOver state.-->
    <VisualTransition To="MouseOver" 
                      GeneratedDuration="0:0:0.5" />

    <!--Take one hundredth of a second to transition from the
        Pressed state to the MouseOver state.-->
    <VisualTransition From="Pressed" To="MouseOver" 
                      GeneratedDuration="0:0:0.01" />

    <!--Take one and a half seconds to transition from the
        MouseOver state to the Normal state. 
        Have the SolidColorBrush, BorderBrush, fade to blue, 
        then to yellow, and then to black in that time.-->
    <VisualTransition From="MouseOver" To="Normal" 
                      GeneratedDuration="0:0:1.5">
      <Storyboard>
        <ColorAnimationUsingKeyFrames
          Storyboard.TargetProperty="Color"
          Storyboard.TargetName="BorderBrush"
          FillBehavior="HoldEnd" >

          <ColorAnimationUsingKeyFrames.KeyFrames>
            <LinearColorKeyFrame Value="Blue" 
              KeyTime="0:0:0.5" />
            <LinearColorKeyFrame Value="Yellow" 
              KeyTime="0:0:1" />
            <LinearColorKeyFrame Value="Black" 
              KeyTime="0:0:1.5" />

          </ColorAnimationUsingKeyFrames.KeyFrames>
        </ColorAnimationUsingKeyFrames>
      </Storyboard>
    </VisualTransition>
  </VisualStateGroup.Transitions>

  <!--The remainder of the VisualStateGroup is the
      same as the previous example.-->

  <VisualState x:Name="Normal" />

  <VisualState x:Name="MouseOver">
    <Storyboard>
      <ColorAnimation 
        Storyboard.TargetName="BorderBrush" 
        Storyboard.TargetProperty="Color" 
        To="Red" />

    </Storyboard>
  </VisualState>

  <VisualState x:Name="Pressed">
    <Storyboard>
      <ColorAnimation 
        Storyboard.TargetName="BorderBrush" 
        Storyboard.TargetProperty="Color" 
        To="Transparent"/>
    </Storyboard>
  </VisualState>

  <!--The Disabled state is omitted for brevity.-->

</VisualStateGroup>

컨트롤 계약을 이해하여 다른 컨트롤 사용자 지정Customizing Other Controls by Understanding the Control Contract

FrameworkElement 개체를 사용 하 여 시각적 구조를 지정 하기 위해 ControlTemplate를 사용 하 고 VisualState 개체를 사용 하 여 시각적 동작을 지정 하는 컨트롤은 파트 컨트롤 모델을 사용 합니다.A control that uses a ControlTemplate to specify its visual structure (by using FrameworkElement objects) and visual behavior (by using VisualState objects) uses the parts control model. WPFWPF 4와 함께 제공되는 많은 컨트롤이 이 모델을 사용합니다.Many of the controls that are included with WPFWPF 4 use this model. ControlTemplate 작성자가 인식 해야 하는 파트는 컨트롤 계약을 통해 전달 됩니다.The parts that a ControlTemplate author needs to be aware of are communicated through the control contract. 컨트롤 계약의 파트를 이해하면 파트 컨트롤 모델을 사용하는 모든 컨트롤의 모양을 사용자 지정할 수 있습니다.When you understand the parts of a control contract, you can customize the appearance of any control that uses the parts control model.

컨트롤 계약에는 세 가지 요소가 있습니다.A control contract has three elements:

  • 컨트롤 논리가 사용하는 시각적 요소The visual elements that the control's logic uses.

  • 컨트롤의 상태 및 각 상태가 속해 있는 그룹The states of the control and the group each state belongs to.

  • 컨트롤에 시각적으로 영향을 미치는 공용 속성The public properties that visually affect the control.

컨트롤 계약의 시각적 요소Visual Elements in the Control Contract

경우에 따라 컨트롤의 논리는 ControlTemplate에 있는 FrameworkElement 상호 작용 합니다.Sometimes a control's logic interacts with a FrameworkElement that is in the ControlTemplate. 예를 들어 컨트롤에서 해당 요소 중 하나의 이벤트를 처리할 수 있습니다.For example, the control might handle an event of one of its elements. 컨트롤에서 ControlTemplate의 특정 FrameworkElement 찾으려는 경우 ControlTemplate 작성자에 게 해당 정보를 전달 해야 합니다.When a control expects to find a particular FrameworkElement in the ControlTemplate, it must convey that information to the ControlTemplate author. 컨트롤은 TemplatePartAttribute를 사용 하 여 예상 되는 요소 형식과 요소의 이름을 전달 합니다.The control uses the TemplatePartAttribute to convey the type of element that is expected, and what the name of the element should be. Button는 해당 컨트롤 계약에 FrameworkElement 부분이 없지만 ComboBox와 같은 다른 컨트롤은 수행 합니다.The Button does not have FrameworkElement parts in its control contract, but other controls, such as the ComboBox, do.

다음 예제에서는 ComboBox 클래스에 지정 된 TemplatePartAttribute 개체를 보여 줍니다.The following example shows the TemplatePartAttribute objects that are specified on the ComboBox class. ComboBox 논리는 PART_EditableTextBox 이라는 TextBoxPART_Popup에서 ControlTemplate이라는 Popup를 찾으려고 합니다.The logic of ComboBox expects to find a TextBox named PART_EditableTextBox and a Popup named PART_Popup in its ControlTemplate.

[TemplatePartAttribute(Name = "PART_EditableTextBox", Type = typeof(TextBox))]
[TemplatePartAttribute(Name = "PART_Popup", Type = typeof(Popup))]
public class ComboBox : ItemsControl
{
}
<TemplatePartAttribute(Name:="PART_EditableTextBox", Type:=GetType(TextBox))> _
<TemplatePartAttribute(Name:="Part_Popup", Type:=GetType(Popup))> _
Public Class ComboBox
    Inherits ItemsControl

End Class

다음 예제에서는 ComboBox 클래스에서 TemplatePartAttribute 개체로 지정 된 요소가 포함 된 ComboBox에 대 한 단순화 된 ControlTemplate를 보여 줍니다.The following example shows a simplified ControlTemplate for the ComboBox that includes the elements that are specified by the TemplatePartAttribute objects on the ComboBox class.

<ControlTemplate TargetType="ComboBox">
  <Grid>
    <ToggleButton x:Name="DropDownToggle"
      HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  
      Margin="-1" HorizontalContentAlignment="Right"
      IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,
                  RelativeSource={RelativeSource TemplatedParent}}">
      <Path x:Name="BtnArrow" Height="4" Width="8" 
        Stretch="Uniform" Margin="0,0,6,0"  Fill="Black"
        Data="F1 M 300,-190L 310,-190L 305,-183L 301,-190 Z " />
    </ToggleButton>
    <ContentPresenter x:Name="ContentPresenter" Margin="6,2,25,2"
      Content="{TemplateBinding SelectionBoxItem}"
      ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
      ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}">
    </ContentPresenter>
    <TextBox x:Name="PART_EditableTextBox"
      Style="{x:Null}"
      Focusable="False"
      Background="{TemplateBinding Background}"
      HorizontalAlignment="Left" 
      VerticalAlignment="Center" 
      Margin="3,3,23,3"
      Visibility="Hidden"
      IsReadOnly="{TemplateBinding IsReadOnly}"/>

    <Popup x:Name="PART_Popup"
      IsOpen="{TemplateBinding IsDropDownOpen}">
      <Border x:Name="PopupBorder" 
        HorizontalAlignment="Stretch" Height="Auto" 
        MinWidth="{TemplateBinding ActualWidth}"
        MaxHeight="{TemplateBinding MaxDropDownHeight}"
        BorderThickness="{TemplateBinding BorderThickness}" 
        BorderBrush="Black" Background="White" CornerRadius="3">
        <ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
          <ItemsPresenter/>
        </ScrollViewer>
      </Border>
    </Popup>

  </Grid>
</ControlTemplate>

컨트롤 계약의 상태States in the Control Contract

컨트롤의 상태도 컨트롤 계약의 파트입니다.The states of a control are also a part of the control contract. Button에 대 한 ControlTemplate를 만드는 예제에서는 상태에 따라 Button 모양을 지정 하는 방법을 보여 줍니다.The example of creating a ControlTemplate for a Button shows how to specify the appearance of a Button depending on its states. 지정 된 각 상태에 대 한 VisualState 만들고이 항목의 이전 상태에 따라 컨트롤의 모양 변경 에 설명 된 대로 VisualStateGroup에서 GroupName을 공유 하는 모든 VisualState 개체를 배치 합니다.You create a VisualState for each specified state and put all VisualState objects that share a GroupName in a VisualStateGroup, as described in Changing the Appearance of a Control Depending on Its State earlier in this topic. 타사 컨트롤은 TemplateVisualStateAttribute를 사용 하 여 상태를 지정 해야 합니다 .이 도구를 사용 하면 Visual Studio의 XAML 디자이너 및 Blend for Visual Studio와 같은 디자이너 도구를 사용 하 여 컨트롤 템플릿 제작을 위한 컨트롤의 상태를 노출할 수 있습니다.Third-party controls should specify states by using the TemplateVisualStateAttribute, which enables designer tools, such as the XAML Designer in Visual Studio and Blend for Visual Studio, to expose the control's states for authoring control templates.

WPFWPF와 함께 제공되는 컨트롤의 컨트롤 계약을 찾으려면 Control 스타일 및 템플릿을 참조하세요.To find the control contract for controls that are included with WPFWPF, see Control Styles and Templates.

컨트롤 계약의 속성Properties in the Control Contract

시각적으로 컨트롤에 영향을 주는 공용 속성도 컨트롤 계약에 포함됩니다.The public properties that visually affect the control are also included in the control contract. 이러한 속성을 설정 하 여 새 ControlTemplate을 만들지 않고 컨트롤의 모양을 변경할 수 있습니다.You can set these properties to change the appearance of the control without creating a new ControlTemplate. TemplateBinding 태그 확장을 사용 하 여 ControlTemplate에 있는 요소의 속성을 Button정의 된 공용 속성에 바인딩할 수도 있습니다.You can also use the TemplateBinding markup extension to bind properties of elements that are in the ControlTemplate to public properties that are defined by the Button.

다음 예제에서는 단추의 컨트롤 계약을 보여 줍니다.The following example shows the control contract for the button.

[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]
[TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
public class Button : ButtonBase
{
    public static readonly DependencyProperty BackgroundProperty;
    public static readonly DependencyProperty BorderBrushProperty;
    public static readonly DependencyProperty BorderThicknessProperty;
    public static readonly DependencyProperty ContentProperty;
    public static readonly DependencyProperty ContentTemplateProperty;
    public static readonly DependencyProperty FontFamilyProperty;
    public static readonly DependencyProperty FontSizeProperty;
    public static readonly DependencyProperty FontStretchProperty;
    public static readonly DependencyProperty FontStyleProperty;
    public static readonly DependencyProperty FontWeightProperty;
    public static readonly DependencyProperty ForegroundProperty;
    public static readonly DependencyProperty HorizontalContentAlignmentProperty;
    public static readonly DependencyProperty PaddingProperty;
    public static readonly DependencyProperty TextAlignmentProperty;
    public static readonly DependencyProperty TextDecorationsProperty;
    public static readonly DependencyProperty TextWrappingProperty;
    public static readonly DependencyProperty VerticalContentAlignmentProperty;

    public Brush Background { get; set; }
    public Brush BorderBrush { get; set; }
    public Thickness BorderThickness { get; set; }
    public object Content { get; set; }
    public DataTemplate ContentTemplate { get; set; }
    public FontFamily FontFamily { get; set; }
    public double FontSize { get; set; }
    public FontStretch FontStretch { get; set; }
    public FontStyle FontStyle { get; set; }
    public FontWeight FontWeight { get; set; }
    public Brush Foreground { get; set; }
    public HorizontalAlignment HorizontalContentAlignment { get; set; }
    public Thickness Padding { get; set; }
    public TextAlignment TextAlignment { get; set; }
    public TextDecorationCollection TextDecorations { get; set; }
    public TextWrapping TextWrapping { get; set; }
    public VerticalAlignment VerticalContentAlignment { get; set; }
}
<TemplateVisualState(Name:="Normal", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="MouseOver", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Pressed", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Disabled", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Unfocused", GroupName:="FocusStates")> _
<TemplateVisualState(Name:="Focused", GroupName:="FocusStates")> _
Public Class Button
    Inherits ButtonBase

    Public Shared ReadOnly BackgroundProperty As DependencyProperty
    Public Shared ReadOnly BorderBrushProperty As DependencyProperty
    Public Shared ReadOnly BorderThicknessProperty As DependencyProperty
    Public Shared ReadOnly ContentProperty As DependencyProperty
    Public Shared ReadOnly ContentTemplateProperty As DependencyProperty
    Public Shared ReadOnly FontFamilyProperty As DependencyProperty
    Public Shared ReadOnly FontSizeProperty As DependencyProperty
    Public Shared ReadOnly FontStretchProperty As DependencyProperty
    Public Shared ReadOnly FontStyleProperty As DependencyProperty
    Public Shared ReadOnly FontWeightProperty As DependencyProperty
    Public Shared ReadOnly ForegroundProperty As DependencyProperty
    Public Shared ReadOnly HorizontalContentAlignmentProperty As DependencyProperty
    Public Shared ReadOnly PaddingProperty As DependencyProperty
    Public Shared ReadOnly TextAlignmentProperty As DependencyProperty
    Public Shared ReadOnly TextDecorationsProperty As DependencyProperty
    Public Shared ReadOnly TextWrappingProperty As DependencyProperty
    Public Shared ReadOnly VerticalContentAlignmentProperty As DependencyProperty

    Public Background As Brush
    Public BorderBrush As Brush
    Public BorderThickness As Thickness
    Public Content As Object
    Public ContentTemplate As DataTemplate
    Public FontFamily As FontFamily
    Public FontSize As Double
    Public FontStretch As FontStretch
    Public FontStyle As FontStyle
    Public FontWeight As FontWeight
    Public Foreground As Brush
    Public HorizontalContentAlignment As HorizontalAlignment
    Public Padding As Thickness
    Public TextAlignment As TextAlignment
    Public TextDecorations As TextDecorationCollection
    Public TextWrapping As TextWrapping
    Public VerticalContentAlignment As VerticalAlignment
End Class

ControlTemplate를 만들 때 기존 ControlTemplate 시작 하 고 변경 하는 것이 가장 쉬운 경우가 많습니다.When creating a ControlTemplate, it is often easiest to begin with an existing ControlTemplate and make changes to it. 다음 중 하나를 수행 하 여 기존 ControlTemplate를 변경할 수 있습니다.You can do one of the following to change an existing ControlTemplate:

완성된 예제Complete Example

다음 예제에서는이 항목에서 설명 하는 전체 ButtonControlTemplate를 보여 줍니다.The following example shows the complete ButtonControlTemplate that is discussed in this topic.

<StackPanel>
  <StackPanel.Resources>
    <Style TargetType="Button" x:Key="newTemplate">
      <!--Set the Background, Foreground, FontSize, Width, 
                  Height, Margin, and Template properties for
                  the Button.-->
      <Setter Property="Background" Value="Navy"/>
      <Setter Property="Foreground" Value="White"/>
      <Setter Property="FontSize" Value="14"/>
      <Setter Property="Width" Value="100"/>
      <Setter Property="Height" Value="40"/>
      <Setter Property="Margin" Value="10"/>
      <Setter Property="HorizontalContentAlignment" Value="Center"/>
      <Setter Property="VerticalContentAlignment" Value="Center"/>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Border x:Name="RootElement">
              <VisualStateManager.VisualStateGroups>

                <!--Define the states and transitions for the common states.
                    The states in the VisualStateGroup are mutually exclusive to
                    each other.-->
                <VisualStateGroup Name="CommonStates">

                  <!--Define the VisualTransitions that can be used when the control
                      transitions between VisualStates that are defined in the
                      VisualStatGroup.-->
                  <VisualStateGroup.Transitions>

                    <!--Take one hundredth of a second to transition to the
                        Pressed state.-->
                    <VisualTransition To="Pressed" 
                                      GeneratedDuration="0:0:0.01" />

                    <!--Take one half second to trasition to the MouseOver state.-->
                    <VisualTransition To="MouseOver" 
                                      GeneratedDuration="0:0:0.5" />

                    <!--Take one hundredth of a second to transition from the
                        Pressed state to the MouseOver state.-->
                    <VisualTransition From="Pressed" To="MouseOver" 
                                      GeneratedDuration="0:0:0.01" />

                    <!--Take one and a half seconds to transition from the
                        MouseOver state to the Normal state. 
                        Have the SolidColorBrush, BorderBrush, fade to blue, 
                        then to yellow, and then to black in that time.-->
                    <VisualTransition From="MouseOver" To="Normal" 
                                          GeneratedDuration="0:0:1.5">
                      <Storyboard>
                        <ColorAnimationUsingKeyFrames
                          Storyboard.TargetProperty="Color"
                          Storyboard.TargetName="BorderBrush"
                          FillBehavior="HoldEnd" >

                          <ColorAnimationUsingKeyFrames.KeyFrames>

                            <LinearColorKeyFrame Value="Blue" 
                              KeyTime="0:0:0.5" />
                            <LinearColorKeyFrame Value="Yellow" 
                              KeyTime="0:0:1" />
                            <LinearColorKeyFrame Value="Black" 
                              KeyTime="0:0:1.5" />

                          </ColorAnimationUsingKeyFrames.KeyFrames>
                        </ColorAnimationUsingKeyFrames>
                      </Storyboard>
                    </VisualTransition>
                  </VisualStateGroup.Transitions>

                  <!--The Normal state is the state the button is in
                      when it is not in another state from this VisualStateGroup.
                      There is no special visual behavior for this state, but
                      the VisualState must be defined in order for the button
                      to return to its initial state.-->
                  <VisualState x:Name="Normal" />

                  <!--Change the border of the button to red when the
                      mouse is over the button.-->
                  <VisualState x:Name="MouseOver">
                    <Storyboard>
                      <ColorAnimation Storyboard.TargetName="BorderBrush"     
                                      Storyboard.TargetProperty="Color"
                                      To="Red" />

                    </Storyboard>
                  </VisualState>

                  <!--Change the border of the button to Transparent when the
                      button is pressed.-->
                  <VisualState x:Name="Pressed">
                    <Storyboard >
                      <ColorAnimation Storyboard.TargetName="BorderBrush" 
                                      Storyboard.TargetProperty="Color" 
                                      To="Transparent" 
                                      />
                    </Storyboard>
                  </VisualState>

                  <!--Show the DisabledRect when the IsEnabled property on
                      the button is false.-->
                  <VisualState x:Name="Disabled">
                    <Storyboard>
                      <DoubleAnimation Storyboard.TargetName="DisabledRect" 
                                       Storyboard.TargetProperty="Opacity"
                                       To="1" Duration="0" />
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>

                <!--Define the states and transitions for the focus states.
                    The states in the VisualStateGroup are mutually exclusive to
                    each other.-->
                <VisualStateGroup x:Name="FocusStates">

                  <!--Define the VisualStates in this VistualStateGroup.-->
                  <VisualState x:Name="Focused">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetName="FocusVisual" 
                        Storyboard.TargetProperty="Visibility" Duration
                        ="0">
                        
                        <DiscreteObjectKeyFrame KeyTime="0">
                          <DiscreteObjectKeyFrame.Value>
                            <Visibility>Visible</Visibility>
                          </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="Unfocused">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetName="FocusVisual" 
                        Storyboard.TargetProperty="Visibility"
                        Duration="0">
                        
                        <DiscreteObjectKeyFrame KeyTime="0">
                          <DiscreteObjectKeyFrame.Value>
                            <Visibility>Collapsed</Visibility>
                          </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>

              <!--Create the SolidColorBrush for the Background 
                  as an object elemment and give it a name so 
                  it can be referred to elsewhere in the control template.-->
              <Border.Background>
                <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
              </Border.Background>

              <!--Create a border that has a different color by adding smaller grid.
                  The background of this grid is specified by the button's Background
                  property.-->
              <Grid Background="{TemplateBinding Background}" Margin="4">

                <!--Create a Rectangle that indicates that the
                    Button has focus.-->
                <Rectangle Name="FocusVisual" 
                           Visibility="Collapsed" Margin="2" 
                           Stroke="{TemplateBinding Foreground}" 
                           StrokeThickness="1" 
                           StrokeDashArray="1.5 1.5"/>

                <!--Use a ContentPresenter to display the Content of
                    the Button.-->
                <ContentPresenter
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                  Margin="4,5,4,4" />

                <!--Create a rectangle that causes the button to appear
                    grayed out when it is disabled.-->
                <Rectangle x:Name="DisabledRect" 
                         Fill="#A5FFFFFF"
                         Opacity="0" IsHitTestVisible="false" />
              </Grid>
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

  </StackPanel.Resources>

  <Button Style="{StaticResource newTemplate}" 
          Content="Button1"/>

  <Button Style="{StaticResource newTemplate}"
          Background="Purple" 
          Content="Button2" />
</StackPanel>

참조See also