Mr-RandomQC
Mr-RandomQC

Reputation: 57

WPF hide and show button depending on datacontext value

I have 2 buttons like so:

<Button x:Name="button1" Content="Button 1"/>
<Button x:Name="button2" Content="Button 2"/>

And I have a bool variable in my DataContext named IsButton1Visible and I would like button1 to be visible and button2 to be collapsed if IsButton1Visible == true and button1 to be collapsed and button2 to be visible if IsButton1Visible == false. Is it possible to accomplish this WITHOUT using style or code-behind? XAML answers are mostly what I am looking for.

Upvotes: 0

Views: 3305

Answers (2)

mm8
mm8

Reputation: 169160

There is a built-in BooleanToVisibilityConverter that can be used to convert between a bool and a Visibility:

<Button x:Name="button1" Content="Button 1">
    <Button.Visibility>
        <Binding Path="IsButton1Visible">
            <Binding.Converter>
                <BooleanToVisibilityConverter />
            </Binding.Converter>
        </Binding>
    </Button.Visibility>
</Button>

You could define your own inverted converter and bind the Visibility property of the second button the same way:

public class BooleanToVisibilityNegationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
        (bool)value ? Visibility.Collapsed : Visibility.Visible;

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
        ((Visibility)value) == Visibility.Visible ? false : true;
}

XAML:

<Button x:Name="button1" Content="Button 1">
    <Button.Visibility>
        <Binding Path="IsButton1Visible">
            <Binding.Converter>
                <local:BooleanToVisibilityNegationConverter />
            </Binding.Converter>
        </Binding>
    </Button.Visibility>
</Button>

This doesn't require any style to be defined or any code-behind to be written but it does require you to define the converter class above.

The other XAML only solution would be define an inline Style for the second button. This requires zero code:

<Button x:Name="button1" Content="Button 1">
    <Button.Visibility>
        <Binding Path="IsButton1Visible">
            <Binding.Converter>
                <BooleanToVisibilityConverter />
            </Binding.Converter>
        </Binding>
    </Button.Visibility>
</Button>

<Button x:Name="button2" Content="Button 2">
    <Button.Style>
        <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsVisible, ElementName=button1}" Value="True">
                    <Setter Property="Visibility" Value="Collapsed" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Upvotes: 1

Mark Feldman
Mark Feldman

Reputation: 16119

Why don't you want to use a style? It's by far the easiest way of doing this.

One way of doing it without a style is by way of boolean-to-visibility converter i.e. something like this:

public class BooleanToVisibilityConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return false;
        var invert = (parameter == null) ? false : Boolean.Parse(parameter.ToString());
        if ((Boolean)value ^ invert)
            return Visibility.Visible;
        else
            return Visibility.Hidden;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Which you would then use like this:

<Button x:Name="button1" Content="Button 1" Visibility="{Binding IsButton1Visible, Converter={StaticResource BooleanToVisibilityConverter}}" />
<Button x:Name="button2" Content="Button 2" Visibility="{Binding IsButton1Visible, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=true}" />

Seriously though, just use a DataTrigger in a style to either change the visibility, or better yet, template the entire control. Converters are what you use when data has to be converted between the view and view model layers, data triggers are what you use when it's one-way only.

Upvotes: 4

Related Questions