본문 바로가기

프로그래밍&IT/C#.WPF

[C# WPF] 첨부 프로퍼티 (Attached Property)란?

의존 프로퍼티 다음 장에 첨부프로퍼티 (Attached Property)가 나온다.

이건 또 뭔가.

확실히 WPF가 윈폼.Winform에 비해서 뭔가 복잡한게 많다.

 

첨부 프로퍼티 (Attached Property)란?

일반적인 의존 프로퍼티(Dependency Property)와 달리 하위 요소가 아닌 다른 요소에 적용할 수 있는 속성을 정의하는 메커니즘입니다.

주로 레이아웃 컨테이너(예: Grid, Canvas)에서 하위 요소의 배치 속성을 정의하는 데 사용됩니다.

WPF의 다양한 컨트롤이 Attached Property를 사용하여 자식 요소의 레이아웃이나 동작을 제어합니다.

Attached Property는 하위 요소가 자신의 프로퍼티를 직접 소유하지 않지만, 해당 요소의 부모 컨테이너가 이 속성을 읽고 적절히 처리할 수 있게 해줍니다.

Attached Property를 사용하는 이유

  1. 자식 요소가 해당 속성을 소유할 필요가 없기 때문에 UI 컨트롤의 재사용성을 높일 수 있습니다.
  2. 레이아웃 컨트롤이 자식 요소의 동작을 제어할 수 있게 해줍니다.
  3. 일반적인 의존 프로퍼티보다 더 유연한 방식으로 UI 요소의 배치를 제어하거나 동작을 확장할 수 있습니다.

이렇게 WPF의 Attached Property는 다양한 컨트롤 간의 관계를 설정하고, 특정 요소가 자신의 프로퍼티를 가지지 않더라도 동작을 조정하는 데 유용하게 사용됩니다.

예시: Attached Property의 이해

가장 일반적인 예로 Grid.Row와 Grid.Column 같은 속성을 들 수 있습니다.

이 속성들은 실제로 Button이나 TextBox가 소유하고 있는 프로퍼티가 아니라 Grid 컨트롤이 정의한 Attached Property입니다.

이러한 속성을 통해 Grid는 자식 요소가 어느 행과 열에 위치할지 알 수 있게 됩니다.

<Grid>
   <Button Content="Button 1" Grid.Row="0" Grid.Column="1"/>
   <TextBox Text="TextBox 1" Grid.Row="1" Grid.Column="0"/>
</Grid>

위 예제에서 Button과 TextBox는 Grid.Row와 Grid.Column이라는 속성을 설정하고 있지만, 이 속성들은 Button과 TextBox 자체가 소유한 프로퍼티가 아니라 Grid가 정의한 Attached Property입니다.

Attached Property 정의 방법

Attached Property는 일반적으로 다음과 같은 경우에 사용됩니다:

  1. 특정 컨트롤이 자신이 소유하지 않은 하위 요소에 대해 추가적인 속성을 정의하고자 할 때.
  2. 컨트롤의 배치 또는 상태를 하위 요소에서 설정하고, 부모 컨테이너가 이 정보를 이용하여 하위 요소의 동작을 제어하고자 할 때.

1. Attached Property 정의

WPF에서 커스텀 Attached Property를 만드는 방법은 의존 프로퍼티를 정의하는 것과 비슷합니다. DependencyProperty.RegisterAttached 메서드를 사용하여 정의합니다.

 

2. Attached Property 예제

Highlight라는 Attached Property를 정의한 클래스를 만듭니다.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfAttachedPropertyExample
{
    public class HighlightHelper : DependencyObject
    {
        // Highlight Attached Property 정의
        public static readonly DependencyProperty HighlightProperty =
            DependencyProperty.RegisterAttached(
                "Highlight", // 속성 이름
                typeof(bool), // 속성 타입
                typeof(HighlightHelper), // 속성 소유 타입
                new PropertyMetadata(false, OnHighlightChanged)); // 기본값과 변경 이벤트 핸들러 등록

        // Get 메서드
        public static bool GetHighlight(UIElement element)
        {
            return (bool)element.GetValue(HighlightProperty);
        }

        // Set 메서드
        public static void SetHighlight(UIElement element, bool value)
        {
            element.SetValue(HighlightProperty, value);
        }

        // Highlight 프로퍼티 변경 시 호출되는 이벤트 핸들러
        private static void OnHighlightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // 요소가 Border 타입인지 확인
            if (d is Border border)
            {
                bool isHighlighted = (bool)e.NewValue;
                
                // Highlight 값이 true이면 배경색을 노란색으로, false이면 원래 색으로 설정
                border.Background = isHighlighted ? Brushes.Yellow : Brushes.Transparent;
            }
        }
    }
}

 

3. XAML에서 Highlight Attached Property 사용

이제 Highlight Attached Property를 사용하여 Border의 자식 요소가 강조 표시될지 여부를 설정합니다.

<Window x:Class="WpfAttachedPropertyExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfAttachedPropertyExample"
        Title="Attached Property Example" Height="300" Width="300">
    <StackPanel>
        <!-- Border 컨트롤 내부에 Attached Property 사용 -->
        <Border local:HighlightHelper.Highlight="True" Width="200" Height="50" Margin="10">
            <TextBlock Text="Highlighted Border" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Border>

        <!-- 강조 표시되지 않는 Border -->
        <Border local:HighlightHelper.Highlight="False" Width="200" Height="50" Margin="10">
            <TextBlock Text="Normal Border" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Border>

        <!-- Button 컨트롤에서도 동일한 Attached Property 사용 -->
        <Button Content="Click Me" local:HighlightHelper.Highlight="True" Margin="10"/>
    </StackPanel>
</Window>

 

4.예제 설명

  • HighlightHelper 클래스는 Highlight라는 이름의 Attached Property를 정의했습니다.
  • OnHighlightChanged 메서드를 사용하여 Highlight가 변경될 때 Border의 배경색을 업데이트합니다.
  • Highlight 속성이 true인 경우 Border의 배경색이 노란색으로 변경됩니다.
  • 이와 같이 Attached Property는 다양한 UI 요소에서 설정 가능하며, Border 뿐만 아니라 다른 컨트롤에서도 사용할 수 있습니다.

5. 주의 사항

  • Attached Property가 특정 컨트롤에서만 작동하게 하려면, 예를 들어 Border 타입에서만 사용되도록 하려면 OnHighlightChanged 메서드에서 d is Border와 같은 형식 확인을 통해 요소를 필터링합니다.
  • Canvas와 같은 이미 정의된 Attached Property가 있는 경우 새로 정의한 Attached Property가 올바르게 작동하지 않을 수 있습니다. 이 경우 새 컨트롤을 정의하거나 이름을 변경하는 등의 방식을 사용해야 합니다.

결론

이 예제에서는 Highlight라는 커스텀 Attached Property를 정의하여 다양한 컨트롤에서 동작을 변경하는 방법을 살펴보았습니다. Canvas의 Left나 Top처럼 이미 존재하는 Attached Property를 덮어쓰지 않도록 주의해야 합니다.