WPF에서 label/button/ _ (밑줄, 언더스코어, underscore) 사라지는 현상 해결하기
WPF(Windows Presentation Foundation)로 개발을 하던중, Label 컨트롤에 content에 _ 를 지정하도록 하면,
_가 사라지는 현상이 있었습니다.
예를 들어, 나는 HELLO_WORLD라고 썼는데, _가 사라진 HELLOWORLD라고 뜨는 현상이었습니다.
원인
아래 주소에 따르면 _가 붙으면 액세스키로 인식한다고 합니다.
액세스키를 누르면 해당 컨트롤에 포커싱이 되도록 개발이 되어 있다고 합니다.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.label?redirectedfrom=MSDN&view=windowsdesktop-6.0
해결법
앞서 살펴본 원인에 대한 설명이 있는 주소에서 해결법을 보면,
Content에 _가 포함되어 있으면, _을 하나 더 쓰는 식으로 대체를 하라고 합니다.
예를 들어, _HELLO_WORLD를 출력하고 싶으면, 아래와 같이 사용을 해야 합니다.
<Label x:Name="test_label" Content="__HELLO__WORLD" />
또 다른 해결법
Label대신에 TextBox UI 컨트롤을 사용하면 굳이 문자열을 수정하지 않아도 됩니다.
앞선 Label과 동일한 텍스트를 출력하려면, 아래와 같이 사용하면 됩니다.
<TextBox x:Name="test_textbox" text="_HELLO_WORLD" />
다른 컨트롤에서의 동일한 문제
_ (밑줄, 언더스코어,underscore)가 사라지는 현상은 Label UI control에서만 일어나는 현상이 아닙니다.
Button이나 CheckBox UI 컨트롤에서도 동일한 현상이 있습니다.
근본적인 해결법
Button이나 CheckBox는 대체할 수 있는 control이 마땅히 존재하지 않습니다.
또한, 언더스코어를 하나 더 쓰는건 원본데이터를 수정하는 방식은 추후 다른 버그를 발생시키거나 trace의 어려움등이 있을수도 있기에,
다른 해결법을 찾아보았습니다.
결론적으로는 아래와 같이 RecognizesAccessKey 속성을 False로 설정하도록 하면 됩니다.
<ContentPresenter RecognizesAccessKey="False" />
좀 더 정확히 표현하자면 아래 코드를 xaml 파일에 추가해줍니다.
<Window.Resources>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type Label}}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Border>
<ContentPresenter RecognizesAccessKey="False" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
전체 xaml은 다음과 같습니다.
<Window x:Class="wpftest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:wpftest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type Label}}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Border>
<ContentPresenter RecognizesAccessKey="False" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Label x:Name="label" Content="__HELLO__WORLD" HorizontalAlignment="Left" Margin="82,40,0,0" VerticalAlignment="Top" Height="53" Width="122"/>
<TextBox x:Name="textBox" Text="_HELLO_WORLD" HorizontalAlignment="Left" Height="23" Margin="82,70,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<CheckBox x:Name="checkBox" Content="_HELLO_WORLD" HorizontalAlignment="Left" Margin="247,51,0,0" VerticalAlignment="Top"/>
<Button x:Name="button" Content="_HELLO_WORLD" HorizontalAlignment="Left" Margin="243,74,0,0" VerticalAlignment="Top" Width="106"/>
</Grid>
</Window>
그러면 아래와 같이 _HELLO_WORLD가 정상적으로 잘 출력이 됩니다.
만일 CheckBox나 Button에 대해서도 적용하려면, Label이라고 써진 부분을 CheckBox나 Button으로 고치면 됩니다.
BasedOn 이 적용이 안될 때
앞선 해결책에서 기본스타일을 주는 BasedOn속성이 있는데요,
일부 환경에서는 이것이 동작하지 않기도 합니다.
이 때에는, 아래와 같이 적용하려는 컨트롤을 우측클릭 ->템플릿 편집 -> 복사본 편집 (영문으로는 Edit Template -> Edit a Copy)하면, style을 생성한다는 팝업이 뜨고 ok를 눌러줍니다.
그러면 새로운 스타일이 생기고, 기존의 스타일을 전부 복사한 sytle태그가 만들어 지게 됩니다.
그 중에서 ContentPresenter태그의 RecognizesAccessKey가 있는 부분을 찾아 속성값을 False로 바꿔주면 됩니다.
총평
_ (언더스코어, 밑줄)은 많이 쓰는 문자라고 생각되는데,
이 문자를 왜 출력안되게 했는지 좀 황당했습니다.
또는 RecognizesAccessKey="False" 가 디폴트 값이 되도록 하는게 오히려 맞지 않은가 싶은데, 아쉬운 설계라고 생각합니다.
WPF가 오래전에 만들어진 기술(2006년)이라 그런지, 지금 관점에서 많이 아쉬운것일 수도 있을거 같긴 합니다.
여러모로 WPF는 참 불편한점이 많은데,
데스크톱 앱을 꼭 만들어야 한다면 레퍼런스도 많은 웹 프로그래밍 쪽으로 고려를 더 우선시 할 것 같습니다.
(대표적으로 electron을 사용하는것으로 우선해보려고 합니다.)
button checkbox label doesn't display "_" character
wpf label button checkbox underscore missing
#microsoft,#wpf,#button,#checkbox,#label,#underscore,#under,#score,#windows,#presentation,#foundation,#마소,#마이크로소프트,#버튼,#체크박스,#언더스코어,#밑줄,#라벨,#레이블
댓글