본문 바로가기

.NET/WPF

[WPF] xaml에서 조건 사용 (조건부 컨트롤 숨기기)

WPF에서 조건에 따라 컨트롤을 숨기려면 Visibility 속성을 사용해서 ViewModel에서 어쩌고 저쩌고...

 

오늘은 xaml에서 간단한 조건에 따라 컨트롤의 속성을 바꿔보도록 하자.

간단하게 텍스트박스에 입력된 텍스트를 오른쪽 버튼의 툴팁으로 표시해 주는 View를 만들었다.

 

View.xaml

<Window x:Class="WpfMvvm.Views.View2"
        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"
        mc:Ignorable="d"
        Title="View2"
        Height="450"
        Width="800">
    <Grid>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center">
            <TextBlock Text="툴팁 텍스트 : "
                       VerticalAlignment="Center" />
            <TextBox Text="{Binding ToolTipText, UpdateSourceTrigger=PropertyChanged}"
                     Width="200"
                     VerticalContentAlignment="Center"
                     Margin="3" />

            <Button Height="40"
                    Margin="3"
                    Content="이곳에 마우스를 올려 툴팁을 확인하세요"
                    ToolTip="{Binding ToolTipText}" />
        </StackPanel>
    </Grid>
</Window>

 

ViewModel.cs

namespace WpfMvvm.ViewModels
{
    internal class View2ViewModel  : ViewModelBase
    {

        private string _toolTipText;
        public string ToolTipText
        {
            get => _toolTipText;
            set => SetProperty( ref _toolTipText, value );
        }

    }
}

 

 


이렇게 마우스를 올리면 잘 동작한다.

 

 

그런데 문제는 이렇게 텍스트박스를 비워둔 경우에, 다시 말해 ToolTipText가 string.Empty인 경우에 발생한다.

ToolTipText가 없을 땐 눈치껏 툴팁이 안 보여야 하지만 그런 거 없이 빈 툴팁 상자를 표시해 버리는 것이다.

xaml 코드를 보았지만 ToolTip이라는 속성 자체에 텍스트를 바인딩하기 때문에 이건 뭐 ToolTip Visibility는 어디서 수정해야 하는지 감도 안 온다. (ToolTipService의 IsEnabled 속성을 사용하여 해결할 수 있긴 하다만 그거대로 문제가 있다. 아래에서 따로 설명하겠다.)

 

이럴 때는 Trigger를 사용하여 속성 값이 변경될 때마다 다른 속성을 바꿔줄 수 있다.

아래와 같이 xaml 코드를 변경했다.

 

<Window x:Class="WpfMvvm.Views.View2"
        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:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="View2"
        Height="450"
        Width="800">
    <Grid>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center">
            <TextBlock Text="툴팁 텍스트 : "
                       VerticalAlignment="Center" />
            <TextBox Text="{Binding ToolTipText, UpdateSourceTrigger=PropertyChanged}"
                     Width="200"
                     VerticalContentAlignment="Center"
                     Margin="3" />

            <Button Height="40"
                    Margin="3"
                    Content="이곳에 마우스를 올려 툴팁을 확인하세요"
                    ToolTip="{Binding ToolTipText}">
                <Button.Resources>
                    <Style TargetType="ToolTip">
                        <Style.Triggers>
                            <Trigger Property="Content"
                                     Value="{x:Static sys:String.Empty}">
                                <Setter Property="Visibility"
                                        Value="Collapsed" />
                            </Trigger>
                            <Trigger Property="Content"
                                     Value="{x:Null}">
                                <Setter Property="Visibility"
                                        Value="Collapsed" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Button.Resources>
            </Button>
        </StackPanel>
    </Grid>
</Window>

 

Button의 리소스에 ToolTip에 대한 Style을 등록해 준다.

Style은 Content가 string.Empty이거나, Null인 경우 Visibility를 Collapsed로 변경하는 두 개의 트리거를 가진다.

String.Empty를 사용하려면 mscorlib 네임스페이스를 가져와야 하므로, Window 태그 본문에 sys를 참조하는 것을 꼭 확인할 것.

 

Trigger는 지정된 조건에 만족하면 Setter를 실행해 주고, 조건에 만족하지 않게 되면 원래 값으로 되돌린다.

이제 코드를 실행하면 텍스트박스가 비어있을 때는 툴팁이 표시되지 않는 것을 볼 수 있다.

 


 

위에서 ToolTipService.IsEnabled 속성에 대해 잠시 언급했는데 간단하게 설명하자면,

이런 식으로 ToolTipService.IsEnabled를 바인딩하고,

ViewModel에서 위와 같이 조건에 따라 ToolTipVisible를 바꿔서 툴팁을 안 보이도록 할 수 있기는 하다.

하지만 치명적인 단점은 

버튼에 마우스 커서를 올려 툴팁을 표시한 상태에서 텍스트박스의 텍스트를 하나씩 지워나가다 보면 텍스트가 모두 지워졌을 때 여전히 빈 툴팁이 표시되는 것을 확인할 수 있다.

이미 툴팁이 떠있는 상태에서는 텍스트가 string.Empty가 되어도 툴팁을 자동으로 닫아주거나 하지는 못하는 것이다.

Trigger를 사용하면 툴팁의 Visibility 자체를 바꿔버리기 때문에 string.Empty가 되는 즉시 툴팁을 사라지게 할 수 있다.