WPF의 컨버터가 호출되지 않을 때 체크해보세요.
제 경우에는 BoolToVisibilityConverter를 만들어서 쓰고 있었습니다. LambdaConverters 패키지를 사용해 간편하게 만들어서요.
해당 컨버터는 bool 소스의 값을 bool ConverterParameter에 따라 Visibility로 변경해주는 역할을 합니다.
패러미터가 true일 때엔 소스가 true라면 Visible, 아니라면 Collapsed를 반환하지만
패러미터가 false일 때엔 반대로 소스가 true라면 Collapsed, 아니라면 Visible을 반환하는 식입니다.
문제는, 이 컨버터를 사용하려 할 때에 발생했습니다.
<DataGrid Binding="{IsRecordExists}", Converter="{x:Static cvt:VisibilityConverters.BoolToVisibilityConverter}", ConverterParameter=True} />
위와 같이 작성하고 테스트를 해보았으나 의도한 바와 전혀 다르게 작동하는 모습을 보였습니다.
왜 의도한 것과 다르게 작동하는지 알아보기 위해 이것 저것 테스트하다가, 컨버터의 Convert 메서드쪽에 브레이크포인트를 걸고 디버그를 돌려보니, 아예 Convert 메서드 쪽으로 진입조차 하지 않는 것을 확인하게 되었죠.
소리 없는 암살자
이건 제가 LambdaConverter 패키지를 사용해서 생긴 문제일 수도 있습니다만, 아무튼 정말 아무런 메세지도, 경고도, 에러도 없이 그냥 메서드 자체가 호출되지 않고 넘어가더군요.
이는 생각보다 심각한 문제였습니다. 에러도 없고 경고도 없어서 이것 저것 쓸데 없는 오만가지를 다 건드리다가 심지어 WPF의 버그인가? 라는 생각도 잠시 스쳐 들 정도였으니까요.
아무튼 그래서 왜 그럴까... 하고 생각하다가 문득 떠오른 것이 있었습니다.
패러미터는 기본적으로 string 형식이다
제가 만든 다른 컨버터에서는 패러미터로 string을 넘겨받고, Convert 메서드 내부에서 파싱 후 처리하는 로직이 있었습니다. 이건 동일한 컨트롤 내에서 잘 작동하고 있다는 사실을 떠올렸더니 바로 원인을 알 수 있었습니다.
VisibilityConverters.BoolToVisibilityConverter는 LambdaConverters의 ValueConverter.Create<I, O, P> 메서드를 통해 생성되었습니다. 그리고 이 메서드의 제네릭 인수로는 bool, Visibility, bool이 들어갔죠.
즉, Parameter의 형식은 bool이 되어야 한다는 얘기입니다. 그러나 저는 string을 쑤셔넣고 있었던 상황입니다.
해결
이후 해결은 굉장히 간단했습니다. 날린 시간이 너무나도 아까울 정도로 간단했죠. 바로 ConverterParameter에 문자열이 아닌 System.Boolean 값을 넣어준 것으로 해결을 봤습니다.
여기에도 두 가지 방법이 있는데, 하나는 아예 바인드를 프로퍼티에서 요소로 빼버리는 식이고,
<DataGrid ...>
<DataGrid.Visibility>
<Binding Source="{...}" Converter="{...}">
<Binding.ConverterParameter><system:Boolean>True<system:Boolean></Binding.ConverterParameter>
</Binding>
</DataGrid.Visibility>
</DataGrid>
다른 하나는 _trueValue, _falseValue 정적 리소스를 만들어 참조하는 방식입니다.
<Grid.Resources>
<system:Boolean x:Key="_trueValue">True</system:Boolean>
<system:Boolean x:Key="_falseValue">False</system:Boolean>
</Grid.Resources>
<-- ... -->
<DataGrid Binding="{IsRecordExists}", Converter="{x:Static cvt:VisibilityConverters.BoolToVisibilityConverter}", ConverterParameter={StaticResource _trueValue}} />
저는 후자가 편해서 후자로 하였습니다.
댓글
댓글 쓰기