Reputation: 57
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
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
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