Sunday, November 28, 2010

Binding to the opposite value of a boolean

In the previous post while I was preparing the example I wanted to bind the Enabled property of two buttons to a single boolean property, something like:

button1.DataBindings.Add("Enabled", _model, "IsTrue");
button2.DataBindings.Add("Enabled", _model, "!IsTrue");

where IsTrue is a boolean property of my _model variable, of course the second line doesn't work as binding only supports binding to properties, so based on this StackOverflow question, I've thrown some lines of codes to achieve something similar:

public class BooleanBinding: Binding
    {
        public BooleanBinding(string propertyName, object dataSource, string dataMember, bool oposite)
            : base(propertyName, dataSource, dataMember)
        {
            if (!oposite) 
                return;
            
            Format += SetOposite;
            Parse += SetOposite;
        }

        private static void SetOposite(object s, ConvertEventArgs e)
        {
            e.Value = !((bool) e.Value);
        }
    }

    public static class BindingExtensions
    {
        public static BooleanBinding Add(this ControlBindingsCollection @this, string propertyName, object dataSource, string dataMember, bool opposite)
        {
            var binding = new BooleanBinding(propertyName, dataSource, dataMember, opposite);
            @this.Add(binding);

            return binding;
        }
    }


The first class named BooleanBinding is a normal Binding with the addition that if the opposite parameter is set to true, there is some event handling on the Parse and Format methods to negate the current `real` boolean value.

The second class is just a helper extension method so we can add a BooleanBinding through the Add method in the Control.Databindings collection.

Here is some example usage in a form that has 2 buttons and 2 checkboxes:
public partial class Form1 : Form
    {
        private Model _model;
        public Form1()
        {
            InitializeComponent();
            _model = new Model();

            button1.DataBindings.Add("Enabled", _model, "IsTrue");
            button2.DataBindings.Add("Enabled", _model, "IsTrue", opposite: true);

            checkBox1.DataBindings.Add("Checked", _model, "IsTrue");
            checkBox2.DataBindings.Add("Checked", _model, "IsTrue", opposite: true);       
        }

        private void button_Click(object sender, EventArgs e)
        {
            _model.IsTrue = !_model.IsTrue;
        }
    }

Consider that if you click on the checkboxes there is a problem with the databinding that is not related to this solution, and is nicely explained in this post: http://turbulentintellect.blogspot.com/2008/07/surviving-winforms-databinding.html

Source code for the example can be found here!

No comments:

Post a Comment