[WPF] MenuItem Header 바인딩시 StringFormat이 작동 안 할 경우 대체 방법
StringFormat?
Binding에서 StringFormat의 지원은 .NetFramework 3.0부터 시작되었습니다. 단순이 바운드된 객체의 값을 보여줄 뿐 아니라, StringFormat 옵션을 통해 더 다양한 옵션으로 텍스트를 표시할 수 있게 되었죠. 예를 들면 아래와 같습니다.
// StringFormat이 없을 때
<TextBlock Text="{Binding SomeDateTime}" />
// => DateTime이 문화권에 따라 표시됨. 예: 2018-08-20 04:23:43
// StringFormat 사용시
<TextBlock Text="{Binding SomeDateTime, StringFormat='yyyy년 MM월 dd일 HH시'}" />
// => 2018년 08월 20일 04시
이는 당연히 문자열 자체에도 사용할 수 있어서 아래와 같이 prefix 또는 suffix를 덧붙이는 작업이 가능하게 됩니다.
// SomeText = "가나다라마"
<TextBlock Text="{Binding SomeText, StringFormat='PREFIX {0} SUFFIX'}" />
// => PREFIX 가나다라마 SUFFIX
참 간편하죠?
문제 발생
그렇게 편하게 사용하던 중, 문제가 발생했습니다. Menu 하위의 MenuItem의 Header 속성에 IPAddress를 바인딩시켜 "현재 아이피는 {0} 입니다."를 표시되게 하고 싶었는데, StringFormat에 굵은 글씨를 그대로 넣어도 현재 아이피만 표시될 뿐, 다른 글자가 나타나지 않는 것이었죠.
그래서 구글링을 열심히 하다가 도저히 방법이 안 보여서, 편법을 썼습니다. 그리고 편법이긴 하지만, 하자 없이 완벽하게 작동합니다. 아래를 보시죠.
<MenuItem>
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="현재 아이피는 " />
<TextBlock Text="{Binding CurrentIpAddress}" />
<TextBlock Text=" 입니다." />
</StackPanel>
</MenuItem.Header>
</MenuItem>
작동 원리
원리는 간단합니다. MenuItem의 Header 프로퍼티는 object 형식이라고 나와있지만, 내부를 살펴보면 HeaderedItemsControl이라는 클래스의 DependencyProperty를 설정하게 되어 있는 것을 알 수 있습니다. 그리고 이 클래스는 주석에도 달려있듯, 여러 항목을 포함하는 헤더 컨트롤을 나타내도록 도와주는 클래스입니다.
때문에, MenuItem.Header 프로퍼티에 StackPanel을 할당할 수 있었던 것이고, StackPanel의 Orientation을 Horizontal로 설정해 하위 컨트롤이 가로로 늘어서게 만든 뒤, 하나씩 하나씩 TextBlock을 추가해 한 줄의 텍스트로 처리하게 된 것이죠.
결론
제목은 MenuItem Header에만 사용할 수 있을 것처럼 짓긴 했지만, 모든 Header 프로퍼티가 있는 WPF 컨트롤에 사용 가능한 팁입니다. 당연히 StringFormat으로 되는 것은 해당 프로퍼티를 사용하는 것이 간편하지만, 안 될 경우에는 이런 편법도 있다는 것을 알고 계셨으면 합니다.
도움!
아직도 왜 IPAddress에 대한 StringFormat이 제대로 작동을 하지 않는지 모르겠습니다. IPAddress의 문제인지, StringFormat의 문제인지, MenuItem.Header의 문제인지 감이 안 잡히네요. 혹시 답을 아시는 분이 계시다면 댓글로 남겨주시면 감사하겠습니다.
댓글
댓글 쓰기