WPF에서 MarkupExtension 선언 위치에 따라 TargetObject 값이 다른 이유에 대해

안녕하세요.
가입하고 처음 질문이네요!

처음으로 어떤 글을 써볼까 많이 고민했습니다.

질문 겸 가입인사네요. :smile:
이렇게 멋진 닷넷 커뮤니티가 있는 줄도 모르고 있었네요.
(요즘 마크다운에 빠져있었는데 완전 감동했어요…)

감사인사 드립니다.

진짜 질문

WPF MarkupExtension에서 TargetObject를 통해 대상 UI객체를 가져오는 기능을 구현했습니다. 여기서 Button에서 직접 MarkupExtension을 사용하면 버튼을 가져올 수 있지만 Style에서 사용하면 버튼을 가져올 수 없습니다.

컨트롤에서 직접 MarkupExtension을 선언했을 때

<Button Content="{local:TestMarkup Extension=Test"/>

ProvideValue에서 TargetObject를 통해 Button 객체을 접근할 수 있습니다.

하지만,

스타일에서 MarkupExtension을 선언했을 때

<Style TargetType="{x:Type Button}" x:Key="BTN">
    <Setter Property="Content" Value="{local:TestMarkup Extension=Test}"/>
</Style>

<Button Style="{StaticResource BTN}"/>

TargetObject는 Button이 아닌 Setter를 반환합니다.

그리고 MarkupExtension 구현 소스코드는 동일합니다.

TestMarkup.cs

public class TestMarkup : MarkupExtension
{
    public string Extension { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var target = (IProvideValueTarget)serviceProvider
            .GetService(typeof(IProvideValueTarget));

        if (target.TargetObject is Button ctl)
        {
            // Yes!!
        }
        return Extension;
    }
}

Style이 Button 컨트롤에 로드되기 전 ProvideValue에서 먼저 호출되기때문에 TargetObject 값이 Button이 아닌 Setter인 것은 겨우 이해는 했지만, 왜 이렇게 동작하는지에 대해 좀 더 이해해보고 싶습니다.

감사합니다. :smile:

2개의 좋아요
<Button Content="{local:TestMarkup Extension=Test}"/>
<Setter Property="Content" Value="{local:TestMarkup Extension=Test}"/>

이 두개만 보시면 됩니다.
말 그대로 확장 마크업 문법이기 때문에 해당 코드를 사용한 Target을 가져옵니다.

그래서 위는 Button이, 아래는 Setter가 나오는 거에요 :slight_smile:

만약 target.TargetProperty를 쓰면 위는 Content를 받고 아래는 Value를 받아요.

4개의 좋아요

@level120
설명해주셔서 정말 감사합니다. :smile:

1개의 좋아요