22

Pretty straightforward: I'm looking to do the same as this but in winforms. Everything that google seems to pull up is wpf specific (ie. I don't want to reference presentationframework.dll)

Explained if you don't want to read the link:

The following is a representation of the intent of what I'd like to do, though it obviously doesn't work.

CheckBox1.DataBindings.Add(new Binding("Checked", this.object, "!SomeBool"));
Community
  • 1
  • 1
Steven Evers
  • 16,649
  • 19
  • 79
  • 126

3 Answers3

28

You have two options:

  1. Create the Binding object manually and attach to the Format and Parse events and swap the value in each.
  2. Create an additional property on the class that just reverses the logic of the intended property

The first option is cleaner, IMO, as it doesn't force your class's API to follow your UI design, though the second option is (marginally) easier.

Example of Option 1

private void SwitchBool(object sender, ConvertEventArgs e)
{ 
    e.Value = !((bool)e.Value);
}

...

Binding bind = new Binding("Checked", this.object, "SomeBool");

bind.Format += SwitchBool;
bind.Parse += SwitchBool;

CheckBox1.DataBindings.Add(bind);

Example of Option 2

public class SomeClass
{
    public bool SomeBool { get; set; }

    public bool NotSomeBool
    {
        get { return !SomeBool; }
        set { SomeBool = !value; }
    }
}

...

CheckBox1.DataBindings.Add("Checked", this.object, "NotSomeBool");

Again, I very much favor option 1, since option 2 requires that you tailor your class to your UI design.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • I was aware of option 2, and I probably should have mentioned that I didn't want to put UI logic in my domain model, which is why I didn't go with it. That said, I did implement the first option successfully. Thank you very much. I want to point out for anyone who might see this in the future: You cannot add that binding to multiple controls, one must be created per UI control (Which is what I was wanting do do). – Steven Evers Mar 17 '10 at 17:14
  • 1
    +1 for the first option, I was trying to solve the same thing. I implemented an extension and a specific 'BooleanBinding' class where you can define if want to bind to the opposite or not based on your solution! I blogged about it here: http://codewithpassion.blogspot.com/2010/11/binding-to-opposite-value-of-boolean.html – Sebastian Piu Nov 28 '10 at 01:17
16

Based on Adam's answer I wrote a small helper class:

class NegateBinding
{
    string propertyName;
    object dataSource;
    string dataMember;
    public NegateBinding(string propertyName, object dataSource, string dataMember)
    {
        this.propertyName = propertyName;
        this.dataSource = dataSource;
        this.dataMember = dataMember;
    }

    public static implicit operator Binding(NegateBinding eb)
    {
        var binding = new Binding(eb.propertyName, eb.dataSource, eb.dataMember, false, DataSourceUpdateMode.OnPropertyChanged);
        binding.Parse += new ConvertEventHandler(negate);
        binding.Format += new ConvertEventHandler(negate);
        return binding;
    }

    static void negate(object sender, ConvertEventArgs e)
    {
        e.Value = !((bool)e.Value);
    }
}

Now you can use it like this:

label1.DataBindings.Add(new NegateBinding("Visible", otherObject, "HasData"));
Tomasz Grobelny
  • 2,666
  • 3
  • 33
  • 43
1

To do this, I´d do a readonly property named NotSomeBool, in the same class where you have the property SomeBool, and bind to this property instead.

Javier
  • 4,051
  • 2
  • 22
  • 20