XAML or HTML

011. 의존 속성(Dependency Property)

XAML 뽀개기

간단한 예제를 통해 Dependency property 대해 알아봅니다. 기본으로 제공되는 UI 컨트롤은 대부분의 속성이 의존 속성으로 되어 있습니다. 기본 TextBox 이용해 입력을 유도하는 가이드 문구를 추가해 사용하는 예제를 만들어 봅니다.


GuideTextBox.cs : 의존 속성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#region GuideText : 가이드 문구
 
public object GuideText
{
    get { return (object)GetValue(GuideTextProperty); }
    set { SetValue(GuideTextProperty, value); }
}
 
public static readonly DependencyProperty GuideTextProperty =
    DependencyProperty.Register(
        "GuideText"
        typeof(object), 
        typeof(GuideTextBox), 
        new PropertyMetadata("Guide Text"));
 
#endregion
 
cs


TextBox 상속 받은 GuideTextBox 클래스를 추가합니다. GuideText를 Dependency property로 추가 정의합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<Style x:Key="Style_GuideTextBox" TargetType="{x:Type ctr:GuideTextBox}">
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    <Setter Property="BorderBrush" Value="#FFABADB3"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="AllowDrop" Value="True"/>
    <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="Template">                
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ctr:GuideTextBox}">
                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                    <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
                    </Trigger>
                    <Trigger Property="IsKeyboardFocused" Value="True">
                        <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsInactiveSelectionHighlightEnabled" Value="True"/>
                <Condition Property="IsSelectionActive" Value="False"/>
            </MultiTrigger.Conditions>
            <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
        </MultiTrigger>
    </Style.Triggers>
</Style>
cs


Style_GuideTextBox Key명으로 스타일을 작성합니다. Blend for VS 템플릿 편집 기능을 이용하면 쉽게 기본 템플릿을 얻을 있습니다.

 

1
2
3
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
    <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
cs

 

기본 템플릿은 최상위 요소가 Border 감싸져 있습니다.

 

1
xmlns:ctr="clr-namespace:Sample.Control"
cs

 

GuideTextBox 사용하기 위해 네임스페이스 선언이 필요합니다.

 

1
2
3
4
5
6
7
8
9
10
11
<ctr:GuideTextBox Height="30" Margin="5" Style="{DynamicResource Style_GuideTextBox}"
                  GuideText="입력해주세요"/>
 
<ctr:GuideTextBox Height="30" Margin="5" Style="{DynamicResource Style_GuideTextBox}" Grid.Column="1">
    <ctr:GuideTextBox.GuideText>
        <StackPanel Orientation="Horizontal">
            <Ellipse Width="10" Height="10" Fill="Red" Margin="5,0"/>
            <TextBlock Text="입력해주세요"/>
        </StackPanel>
    </ctr:GuideTextBox.GuideText>
</ctr:GuideTextBox>
cs

 

태스트를 위한 GuideTextBox를 XAML 작성합니다. 첫번째는 문자열만 두번째는 복잡하게 구성했습니다.

 

 

이것만으로는 가이드 문구를 표시할 없습니다. 스타일 Template을 수정해야 합니다.

 

1
2
3
4
5
6
7
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
    <Grid>
        <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
        
        <Label x:Name="PART_GuideText" Content="{TemplateBinding GuideText}" Foreground="Red"/>
    </Grid>
</Border>
cs

 

Border는 하나의 자식만 가질 있으므로 Grid로 한번 감싸주었습니다. 그리고 가이드 문구를 TextBlock으로 간단히 정의할 있지만 복잡한 구성이 가능케 하기위해 Label 정의했습니다. TextBlock Text 속성은 문자열 타입만 자식으로 가질 있고 Label Content Object 타입을 가질 있습니다. 반드시 Label이어야하는 것은 아닙니다. 자세한 설명은 여기서 다루지 않습니다.

 

 


Dependency property 추가해 자유롭게 변경 가능한 가이드 문구를 추가했습니다. 간단한 예를 들었지만 다양한 방식으로 응용할 있을 것입니다.


 

이어서 다음 포스트에서는 Value Converter 이용해 입력한 Text 있을 때처럼 가이드 문구가 이상 필요하지 않을 자동으로 보이지 않도록 하는 방법을 알아보려 합니다.


Dependency property에 대한 더 자세한 내용은 박문찬 MVP님의 블로그를 참고하세요.


샘플 코드 : https://github.com/CharlesKwon/XamlSimplified