WPF element databinding for IsEnabled (but for false)
Asked Answered
F

4

5

I'm a starter in WPF, and there's something I can't seem to figure out.

I have a CheckBox that I would like to disable when a RadioButton is not selected. My current syntax is:

<CheckBox IsEnabled="{Binding ElementName=rbBoth, Path=IsChecked}">Show all</CheckBox>

So basically, I want IsEnabled to take the opposite value than the binding expression I'm currently supplying.

How can I do this? Thanks.

Fief answered 23/6, 2010 at 6:36 Comment(0)
E
20

You need to use what's called a value converter (a class that implements IValueConverter.) A very basic example of such a class is shown below. (Watch for clipping...)

public class NegateConverter : IValueConverter
{

    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
    {
        if ( value is bool ) {
            return !(bool)value;
        }
        return value;
    }

    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
    {
        if ( value is bool ) {
            return !(bool)value;
        }
        return value;
    }

}

Then to include it in your XAML you would do something like:

<UserControl xmlns:local="clr-namespace:MyNamespace">
    <UserControl.Resources>
        <local:NegateConverter x:Key="negate" />
    </UserControl.Resources>

    ...
    <CheckBox IsEnabled="{Binding IsChecked, ElementName=rbBoth, Converter={StaticResource negate}}"
              Content="Show all" />

</UserControl>
Edelstein answered 23/6, 2010 at 6:46 Comment(8)
Yeah... I thought about that, but I was trying to see if there's a more direct approach.Fief
As you use WPF more and more you'll find that you create a pretty sophisticated set of converters and the design of them is typically very reusable. In fact, I do have a NegateConverter but it's much more robust than my example. It negates numerics, booleans, Visibility, Thickness, etc. Just one of about a dozen converters I use frequently.Edelstein
Josh: How do you negate a Thickness?Heterogenesis
var thickness2 = new Thickness(-t1.Left, -t1.Top, -t1.Right, -t1.Bottom);Edelstein
Here actually I just blogged about it... josheinstein.com/blog/index.php/2010/06/…Edelstein
Add some sugar... return ( value is bool ) ? !(bool)value : value;Adrenocorticotropic
Josh: I guess I'm having trouble figuring out what circumstances would ever call for negating a Thickness.Heterogenesis
You need to (pun intended) "think outside the box". For example, inside a template if I wanted an element to have a negative margin equal to the border thickness of the templated parent. Or to "cancel out" the padding of a containing element.Edelstein
L
3
<CheckBox>
                    <CheckBox.Style>
                        <Style TargetType="CheckBox">
                            <Setter Property="Visibility" Value="Visible" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsShowName }" Value="true">
                                    <Setter Property="Visibility" Value="Collapsed" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </CheckBox.Style>
  </CheckBox>
Leopoldine answered 10/8, 2016 at 8:17 Comment(0)
A
0

Your current syntax already serves your need. It will disable the checkbox if the radiobutton is not checked.

If you really want to invert the scenario, all you need is a Converter. Take a look at this sample.

Adrenocorticotropic answered 23/6, 2010 at 6:48 Comment(0)
C
0

How about this one:

Create a converter for booleans:

class BooleanValueInverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(parameter is IValueConverter))
        {
            if (value is bool)
                return !(bool)value;
            else
                return DependencyProperty.UnsetValue;
        }
        else
        {
            IValueConverter converter = (IValueConverter)parameter;
            if (value is bool)
            {
                bool input = !(bool)value;
                return converter.Convert(input, targetType, null, culture);
            }
            else
            {
                return DependencyProperty.UnsetValue;
            }
        }
    }

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

in the xaml import the namespace where the inverter class is implemented:

xmlns:util="clr-namespace:MyApp.Utilities"

In the resource section add reference the inverter class:

<util:BooleanValueInverter x:Key="Inverter" />

And then just simply use it like this:

<TextBox Text="{Binding Path=TextProperty}" IsEnabled="{Binding SomeBoolPropertyToInvert, Converter={StaticResource Inverter}}"/>
Concepcionconcept answered 2/8, 2015 at 12:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.