XAML or HTML

013. 속성 상속(Resolved Dynamically)

XAML 뽀개기

프로젝트에서 XAML 코드 작업을 하다보면 점점 늘어나는 코드 양에 스트레스를 받을 때가 간혹 있습니다. Style 묶어 관리하기도 하고 Resource Dictionary 파일을 여러 나누어 관리도 하면서 나름대로의 효율을 찾아서 자신만의 스타일을 갖게 됩니다.

       

1
2
3
4
5
6
7
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    <Label Content="Local property" FontSize="12" FontFamily="Gulim" FontWeight="Bold" FontStyle="Italic"/>
    <TextBlock Text="Lorem Ipsum is simply " FontSize="12" FontFamily="Gulim" FontWeight="Bold" FontStyle="Italic"/>
    <TextBlock Text="dummy text of the" FontSize="12" FontFamily="Gulim" FontWeight="Bold" FontStyle="Italic"/>
    <TextBlock Text="printing and typesetting " FontSize="12" FontFamily="Gulim" FontWeight="Bold" FontStyle="Italic"/>
    <TextBlock Text="industry." FontSize="12" FontFamily="Gulim" FontWeight="Bold" FontStyle="Italic"/>
</StackPanel>
cs

 

 

이해를 돕기위해 극단적으로 예제를 들고자합니다. 텍스트의 Font 관련된 속성들을 보면 FontSize, FontFamily, FontWeight, FontStyle, FontStretch, Foreground 많은 속성들이 사용됩니다. 앞에서 이야기했 이런 복잡함은 스타일, 리소스딕셔너리 다양한 방법들을 이용해 효율적으로 관리될 있습니다.

 

그런데 일반적으로 Label, TextBlock 문자열 표시에 사용되는 컨트롤들은 단독으로 흔히 사용되지 않습니다. 다른 컨트롤도 마찬가지입니다. Grid, StackPanel, ScrollViewer 다양한 패널(Panel) 자식으로 사용됩니다.

 

1
2
3
4
5
6
7
<StackPanel ChildrenFontSize="15">
    <Label Content="Local property"/>
    <TextBlock Text="Lorem Ipsum is simply "/>
    <TextBlock Text="dummy text of the"/>
    <TextBlock Text="printing and typesetting "/>
    <TextBlock Text="industry."/>
</StackPanel>
cs

 

이런 환경 구조 안에서 패널이 자식의 속성을 일괄적으로 적용해주면 어떨까요? 그러면 어떤면에서 효율적이면서도 XAML 코드를 조금이나마 작성할 있지않을까요? 다시 한번 말하지만 예제를 위한 설정입니다. 어떤 방법이든지 자신만의 스타일과 그러한 결정에 따른 장점과 단점은 항상 존재하는 법입니다.

 

1
2
3
4
5
6
7
<StackPanel FontSize="15">
    <Label Content="Attached property"/>
    <TextBlock Text="Lorem Ipsum is simply "/>
    <TextBlock Text="dummy text of the"/>
    <TextBlock Text="printing and typesetting "/>
    <TextBlock Text="industry."/>
</StackPanel>
cs

 

StackPanel은 FontSize 속성이 없기 때문에 에러가 발생합니다. StackPanel을 상속 받아서 새로운 패널 컨트롤(Custom Control) 만들 수도 있습니다. 그러면 일이 쉽게 풀릴지도 모르겠습니다.

 

1
2
3
4
5
6
7
8
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1"
            TextBlock.FontSize="15" TextBlock.Foreground="Red">        
    <Label Content="Attached property"/>
    <TextBlock Text="Lorem Ipsum is simply "/>
    <TextBlock Text="dummy text of the"/>
    <TextBlock Text="printing and typesetting "/>
    <TextBlock Text="industry."/>
</StackPanel>
cs

 

이런 방법은 어떨까요? Class명과 함께 속성을 정의하는 것이 가능합니다. VisualTree 요소들은 부모의 속성을 상속 받으려는 특성이 있기 때문에 이러한 동작이 가능합니다. 자세한 설명은 생략합니다. 더 자세한 내용은 박문찬 MVP님의 블로그를 참고하세요.

 

 

하지만 Foreground 속성은 영향을 미치지 못하는 한계가 있습니다. 문자열을 표현하는데 있어서 Foreground 속성을 무시할 수는 없습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1">
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontSize" Value="15"/>
        </Style>
        <Style TargetType="Label">
            <Setter Property="FontSize" Value="15"/>
        </Style>
    </StackPanel.Resources>
 
    <Label Content="Attached property"/>
    <TextBlock Text="Lorem Ipsum is simply "/>
    <TextBlock Text="dummy text of the"/>
    <TextBlock Text="printing and typesetting "/>
    <TextBlock Text="industry."/>
</StackPanel>
cs

 

이런 식의 코드도 작성 가능합니다. 저도 많이 사용하는 방법 중에 하나입니다. 저런 식의 리소스 선언은 하위 컨트롤에만 영향을 준다는 점이 매우 매력적입니다. Style의 BasedOn 속성을 이용해 기존의 스타일도 재사용할 수 있는 점도 아주 매력적입니다. 방법의 단점은 다양한 컨트롤이 복합적으로 존재할 경우 코드가 많이 늘어난다는 점입니다


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