1

When I check all three check boxes, and uncheck only the last, then both the first and the last get unchecked.

Other such mysterious behaviour occurs when playing around with the check boxes.

After having dug a few hours already, here the scenario.

I have this form:

enter image description here

The check boxes are data bound using a BindingSource. The BindingSource is bound to my domain object.

Inquiry

public class Inquiry {
    public virtual IList<Report> Reports{ get; protected set; }
    public bool DomaineMedicament { 
        get { hasReport(ReporType.DomaineMedicament); }
        set { 
            if (value) addReport(ReportType.DomaineMedicament);
            else removeReport(ReportType.DomaineMedicament);
        }
    }
    // Same code for the other bound boolean values...          

   private void addReport(ReportType report) {
       // Can only contain one for each type at any time
       if (hasReport(report)) return; 

       Report adding = new Report() { Type = report, Inquiry=this; };
       Reports.Add(adding);
   } 

   private bool hasReport(ReportType report) {
       return 0 < Reports.Count(r => r != null && r.Type == report);
   }

   private void removeReport(ReportType report) {
       if (hasReport(report)) 
           Reports.Remove(Rapports.Single(r => r.Type == report));           
   }       
}

The data binding of my check boxes is defined at design-time as follows:

DataBindings | Checked | inquiryBindingSource - DomaineMedicament

The Form

public partial class NouvelleDemandeForm : Form {
    public NouvelleDemandeForm() { 
        InitializeComponent();
        inquiredAtDateTimePicker.MaxDate = DateTime.Today.AddDays(-1);
        inquiryBindingSource.CurrentItemChanged += (sender, e) => {
            createNewInquiryButton.Enabled = 
                DataContext.AllRequiredInformationIsProvided;
        };
    }

    public DemandeAccesInformation DataContext { 
        get { return (DemandeAccesInformation)inquiryBindingSource.DataSource; }
        set { inquiryBindingSource.DataSource = value; } 
    }
}

And in the advanced DataBindings settings, the update is set to occur OnPropertyChanged.

I have investigated using breakpoints, and also written unit tests, I can't find out what's happening.

Related unit tests

[TestClass]
public class InquiryTests{
    [TestMethod]
    public void IShouldCountThreeWhenAddingThreeReports() {
        givenIHaveANewInquiry();
        whenIAddTheThreeReports();
        thenIShouldCount(3);
    }

    [TestMethod]
    public void IShouldCountTwoWhenAddingThreeReportsAndRemovingOne() {
        givenIHaveANewInquiry();
        whenIAddTheThreeReports();
        whenIRemove(ReportType.RegistreDesRefus);
        thenIShouldCount(2);
    }

    private void givenIHaveANewInquiry() { inquiry = new Inquiry(); }

    private void whenIAddTheThreeReports() {
        inquiry.DomaineMedicament = true;
        inquiry.OrdonnanceElectronique = true;
        inquiry.RegistreDesRefus = true;
    }

    private void whenIRemove(ReportType report) {
        inquiry.Reports.Remove(inquiry.Reports.Single(r => r.Type == report));
    }

    private void thenIShouldCount(int expectedReportCount) {
        Assert.AreEqual(expectedReportCount, inquiry.Reports.Count);
    }

    private Inquiry inquiry;
}

Both tests pass!

I am kind of lost here. Any thoughts of any possible issues?

EDIT

I have handled the check boxes CheckedChanged event manually as stated in this answer.

Now, sometimes, when I check all three check boxes and uncheck them afterwards, my button remains enabled, which it shall not.

Here's how I handle the CheckedChanged event manually.

electronicPrescriptionCheckBox.CheckedChanged += (sender, e) => {
    addRemoveReport(electronicPrescriptionCheckBox.Checked
        , RapportAccesInformation.TypeRapport.OrdonnanceElectronique);
};

private void addRemoveReport(bool addRemove
    , ReportType report) {
    switch (report) {
        case ReportType.DomaineMedicament:  
            DataContext.DomaineMedicament = addRemove; 
            break;
        case ReportType.OrdonnanceElectronique:  
            DataContext.OrdonnanceElectronique = addRemove; 
            break;
        case ReportType.RegistreDesRefus:   
            DataContext.RegistreDesRefus = addRemove; 
            break;
    }

    inquiryBindingSource.ResetCurrentItem();
}
Community
  • 1
  • 1
Will Marcouiller
  • 23,773
  • 22
  • 96
  • 162
  • I presume this is win forms? – Sayse Apr 07 '14 at 16:28
  • 3
    I had a [similar issue](http://stackoverflow.com/questions/16980942/update-databinding-on-lost-focus-winforms) with winforms where to overcome this I had to explicitly reset the desired boxes. Wpf doesn't have this issue – Sayse Apr 07 '14 at 16:30
  • @Sayse, I have edited my question to reflect the changes. Now, when I intend to remove all the reports by unchecking the three check boxes, it looks like only one report doesn't wish to be removed, that is, that third in a `CheckBox` point of view. I really don't get it. I've been working on this bug all day. =( – Will Marcouiller Apr 07 '14 at 19:49
  • Have you checked if the sender is the same button as the one you just unchecked? if not this is probably your issue :) (assuming my earlier link helped!) – Sayse Apr 07 '14 at 19:56
  • Edit to above: you currently check against the checkboxes variable instead of the sender, what i mean is you may wish to ignore this update when the sender , if memory serves me, may be null (P.S the link I posted also took me days :p) – Sayse Apr 07 '14 at 20:04
  • I had not thought of it, actually. Thanks for the information. Meanwhile, I have made the `CheckedChanged` event call a helper method which in turn refreshes the `DataContext.Reports` based on the check boxes `Checked` property value, each time for the three of them. It sounds like it's working now, but this is a dirty fix that I shall get busy with for a few hours still. – Will Marcouiller Apr 07 '14 at 20:41
  • No worries glad I could help, just important to note that winforms databinding updates the whole source not just the property.. I ended up with a few ugly fixes/hacks which is one of the reasons I hope to go back to the project sometime to convert to wpf – Sayse Apr 07 '14 at 20:48

1 Answers1

0

This seems to be a WinForms DataBinding flaw as per this question linked by @Sayse.

Update Databinding on lost focus (Winforms)

I ended up doing manual processing of CheckBox.CheckedChanged events, and ensuring that the object actually reflected the very state the the check boxes each time a CheckedChanged occurs.

Community
  • 1
  • 1
Will Marcouiller
  • 23,773
  • 22
  • 96
  • 162