21

I have button:

<Button Content="Stop loading" />

In ViewModel i have property IsLoaded. I don't want to write property IsNotLoaded but i want to use IsLoaded in binding and disable button when IsLoaded = true.

How implement something like this:

<Button Content="Stop loading" IsEnabled="{Binding !IsLoaded}" />

P.S. if it more difficult than writing of additional property, i will use IsNotLoaded property.

Rover
  • 2,203
  • 3
  • 24
  • 44
  • 2
    See [this SO question](http://stackoverflow.com/questions/1039636/how-to-bind-inverse-boolean-properties-in-wpf) – Nekresh Jan 28 '11 at 16:27

4 Answers4

26

The standard means of doing this is to make an IValueConverter that will invert your boolean values. While creating this class is more difficult than adding a new property, it's completely reusable - so later, you can reuse this in other bindings (without polluting your ViewModel with lots of !Property properties).

This class would look something like:

[ValueConversion(typeof(bool), typeof(bool))]
public class InvertBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool booleanValue = (bool)value;
        return !booleanValue;
    }

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

Then, you would add it to your resources:

<src:InvertBoolConverter x:Key="invertBoolConverter"/>

Once you have this, you would use it like:

<Button Content="Stop loading" 
        IsEnabled="{Binding IsLoaded, Converter={StaticResource invertBoolConverter}}" 
/>
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    You'd think Microsoft would provide one of these. They already provide BooleanToVisibilityConverter. Why not a handful of other helpful ones? – NielW Mar 24 '18 at 22:54
12

While the converter answers are all valid, you may want to look at an alternative methodology: Commanding.

In WPF (and somewhat in Silverlight), you can bind an ICommand to that button. So, if you created, on your ViewModel, a property called CancelLoadingCommand that implemented ICommand, you'd bind the button as follows:

<Button Content="Stop Loading" Command="{Binding CancelLoadingCommand}" />

The implementation of the CancelLoadingCommand in your ViewModel would look something like:

    public ICommand CancelLoadingCommand
    {
        get
        {
            if (_cancelLoadingCommand== null)
            {
                this._cancelLoadingCommand= new RelayCommand(
                    delegate
                    {
                        // Cancel the loading process.
                    },
                    delegate
                    {
                        return !this.IsLoaded;
                    }
                );
            }

            return _cancelLoadingCommand;
        }
    }

Note, I'm using a RelayCommand here (which is part of the PRISM or MVVM-Light frameworks). I'd suggest looking into one of those as well.

I hope this helps.

SergioL
  • 4,905
  • 3
  • 26
  • 30
7

One solution is to use a converter to invert the boolean value. Something like

public class InvertedBoolenConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return !(bool)value;

    }

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

Then add the converter to a resource somewhere and use it in the binding:

<YourUserControl.Resources>
   <c:InvertedBoolenConverter x:Key="InvertedBoolenConverter" />
</YourUserControl.Resources>

<Button Content="Stop loading" IsEnabled="{Binding IsLoaded,Converter={StaticResource InvertedBoolenConverter}}" />
James Hay
  • 12,580
  • 8
  • 44
  • 67
6

You want to use a converter. Here is one that will do the trick for you.

  public class booleaninverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      return !(bool)value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      return !(bool)value;
    }
  }

To use it, write your xaml like so

<Button Content="Stop loading" IsEnabled="{Binding IsLoaded, Converter={StaticResource booleaninverter}" />

You can make the static resource in your App.xaml, or other window / control resources section. Of course you have to make the 'local' namespace declarations and what-not, but this is most of the work done for you.

<local:booleaninverter x:key="booleaninverter"/>
A.R.
  • 15,405
  • 19
  • 77
  • 123