Question

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();
}
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top