views:

716

answers:

2

I'm writing a desktop application in Visual Studio 2008 / C#

I finished (mostly) writing an engine which generates a working schedule for the week for a small company; a form of a course-scheduling problem

Right now I'm designing a form in which the user can determine the initial parameters, or criteria, for the engine to adhere to (as some settings are optional)

I've got a class named EngineParameters, which holds all of those settings.

For the purpose of databinding, I created a bndEngineParameters class, which encapsulates all the relevant fields with getters and setters

public class bndEngineParameters
    {
        private engineParameters _parameters;

        public bndEngineParameters(engineParameters ep)
        {
            this._parameters = ep;                
        }

        public bool avoidGrouping
        {
            get { return _parameters.avoidGrouping; }
            set { _parameters.avoidGrouping = value; }
        }

        public bool avoidWeekends
        {
            get { return _parameters.avoidWeekends; }
            set { _parameters.avoidWeekends = value; }

        }

        public bool keyFlow
        {
            get { return _parameters.keyFlow; }
            set { _parameters.keyFlow = value; }
        }

        public bool keyFlowAssistants
        {
            get { return _parameters.keyFlowAssistants; }
            set { _parameters.keyFlowAssistants = value; }
        }        
    }

It's not complete - there will be int values (maximum number of hours one can work etc.); I want those bool values to be bound to checkboxes on my form

And it's at that trivial task where I surprisingly ran into problems

Using "Add New DataSource" wizard, I created a binding source

private System.Windows.Forms.BindingSource bndEngineParametersBindingSource;

I then bound the Checked property of my Checkbox to the respective property of my binding source:

alt text

I implemented a local variable boundParameters so that I get an access to the parameters set by the user

  public partial class formGenerateRota : Form
    {

        public bndEngineParameters boundParameters;

        // (...)

        public formGenerateRota()
        {
            InitializeComponent();
        }        

        private void formGenerateRota_Load(object sender, EventArgs e)
        {
            boundParameters = new bndEngineParameters(new engineParameters());
            bndEngineParametersBindingSource.Add(boundParameters);            
        }

        // (...)
}

And what? Nothing happens. There is an bndEngineParameters object under bndEngineParametersBindingSource.Current (in run-time of course), but the avoidWeekends value never changes (when I check the checkbox on and off), and the bndEngineParametersBindingSource_CurrentItemChanged event is never fired

What's wrong?


SORRY! it does change, but only after the checkbox loses focus (after validation).

I'm stupid sometimes

If I'm doing something wrong anyway (I'm not any good with data binding), I'd very much appreciate if you point it out of course!

+1  A: 

Two common issues:

  • set the DataSourceUpdateMode to OnPropertyChanged
  • (optional) to receive changes from the object, implement the {name}Changed event pattern or INotifyPropertyChanged

To be honest though, I'm sure most of that isn't necessary; you should just be able to say:

myCheckbox.Bindings.Add("Checked", myEngineParameters, "avoidWeekends",
    false, DataSourceUpdateMode.OnPropertyChanged);

Full example:

using System;
using System.Diagnostics;
using System.Windows.Forms;

class EngineParameters {
    private bool avoidWeekends;
    public bool AvoidWeekends {
        get { return avoidWeekends; }
        set {
            avoidWeekends = value;
            Debug.WriteLine("AvoidWeekends => " + value);
        }
    }
}
static class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();            
        using(Form form = new Form())
        using (CheckBox myCheckbox = new CheckBox()) {
            EngineParameters myEngineParameters = new EngineParameters();
            myEngineParameters.AvoidWeekends = true;    
            form.Controls.Add(myCheckbox);
            myCheckbox.DataBindings.Add("Checked", myEngineParameters, "AvoidWeekends",
                false, DataSourceUpdateMode.OnPropertyChanged);
            Application.Run(form);
        }
    }
}
Marc Gravell
+1  A: 

Instead of this:

bndEngineParametersBindingSource.Add(boundParameters);

do this:

bndEngineParametersBindingSource.DataSource = boundParameters;
Pavel Minaev