Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind inverse boolean properties in WPF?

What I have is an object that has an IsReadOnly property. If this property is true, I would like to set the IsEnabled property on a Button, ( for example ), to false.

I would like to believe that I can do it as easily as IsEnabled="{Binding Path=!IsReadOnly}" but that doesn't fly with WPF.

Am I relegated to having to go through all of the style settings? Just seems too wordy for something as simple as setting one bool to the inverse of another bool.

<Button.Style>
    <Style TargetType="{x:Type Button}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="True">
                <Setter Property="IsEnabled" Value="False" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="False">
                <Setter Property="IsEnabled" Value="True" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Button.Style>
like image 255
Russ Avatar asked Jun 24 '09 16:06

Russ


4 Answers

You can use a ValueConverter that inverts a bool property for you.

XAML:

IsEnabled="{Binding Path=IsReadOnly, Converter={StaticResource InverseBooleanConverter}}"

Converter:

[ValueConversion(typeof(bool), typeof(bool))]
    public class InverseBooleanConverter: IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            if (targetType != typeof(bool))
                throw new InvalidOperationException("The target must be a boolean");

            return !(bool)value;
        }

        public object ConvertBack(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        #endregion
    }
like image 132
Chris Nicol Avatar answered Nov 17 '22 17:11

Chris Nicol


Have you considered an IsNotReadOnly property? If the object being bound is a ViewModel in a MVVM domain, then the additional property makes perfect sense. If it's a direct Entity model, you might consider composition and presenting a specialized ViewModel of your entity to the form.

like image 27
Paul Alexander Avatar answered Nov 17 '22 17:11

Paul Alexander


With standard bindings you need to use converters that look a little windy. So, I recommend you to look at my project CalcBinding, which was developed specifically to resolve this problem and some others. With advanced binding you can write expressions with many source properties directly in xaml. Say, you can write something like:

<Button IsEnabled="{c:Binding Path=!IsReadOnly}" />

or

<Button Content="{c:Binding ElementName=grid, Path=ActualWidth+Height}"/>

or

<Label Content="{c:Binding A+B+C }" />

or

<Button Visibility="{c:Binding IsChecked, FalseToVisibility=Hidden}" />

where A, B, C, IsChecked - properties of viewModel and it will work properly

like image 88
Alex141 Avatar answered Nov 17 '22 17:11

Alex141


I would recommend using https://github.com/JohannesMoersch/QuickConverter

Inverting a boolean is then as simple as: <Button IsEnabled="{qc:Binding '!$P', P={Binding IsReadOnly}}" />

That speeds the time normally needed to write converters.

like image 22
Noxxys Avatar answered Nov 17 '22 17:11

Noxxys