0

I have two forms - one is the main form:

enter image description here

And the second is for adding or editing information:

enter image description here

When I click the edit button my second form shows up filled with selected person I want to change. I am changing first name and then click on the cancel button but the name of the selected person is already changed. What is the reason? How can I fix it? It might be some problems with DataBinding.

Here is my code for main form:

 public partial class FormEmployees : Form
 {
        List<Employee> employees;
        BindingSource bsEmployee;

        public FormEmployees()
        {
            InitializeComponent();
            bsEmployee = new BindingSource();

            employees = Storage.GetEmployee();
            lbEmployees.DisplayMember = "FullName";
            lbEmployees.ValueMember = "EmployeeId";
            bsEmployee.DataSource = employees;
            lbEmployees.DataSource = bsEmployee;
        }

        private void btEdit_Click(object sender, EventArgs e)
        {
            Employee emp = bsEmployee.Current as Employee;
            FormEdit formEdit = new FormEdit(emp);

            if (formEdit.ShowDialog() == DialogResult.OK)
            {
                bsEmployee.ResetBindings(true);
            }
        }

        private void btAdd_Click(object sender, EventArgs e)
        {
            Employee emp = new Employee
            {
                FirstName = "Input Data",
                Birthday = DateTime.Now.AddYears(-16)
            };

            FormEdit formEdit = new FormEdit(emp);

            if (formEdit.ShowDialog() == DialogResult.OK)
            {
                bsEmployee.Add(emp);
                bsEmployee.ResetBindings(true);
            }
        }

        private void btDelete_Click(object sender, EventArgs e)
        {
            Employee emp = bsEmployee.Current as Employee;

            if(MessageBox.Show("Do you want to delete it?", "Deleting record...", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                bsEmployee.Remove(emp);
                bsEmployee.ResetBindings(true);
            }
        }
}

Here is my code for the additional form

public partial class FormEdit : Form
{
        Employee employee;
        BindingSource bs = new BindingSource(); 

        public FormEdit(Employee employee)
        {
            InitializeComponent();
            this.employee = employee;
            bs.DataSource = this.employee;
            tbFirstName.DataBindings.Add("Text", bs, "FirstName", false, DataSourceUpdateMode.OnPropertyChanged);
            tbLastName.DataBindings.Add("Text", bs, "LastName", false, DataSourceUpdateMode.OnPropertyChanged);
            tbInn.DataBindings.Add("Text", bs, "INN", false, DataSourceUpdateMode.OnPropertyChanged);
            dtmBirthday.DataBindings.Add("Value", bs,"Birthday",
                false, DataSourceUpdateMode.OnPropertyChanged);
        }

        private void btCancel_Click(object sender, EventArgs e)
        {
            Close();
        }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Alex
  • 146
  • 9
  • 2
    It's been a long time since I used winforms, but I'm pretty sure you should be setting `this.DialogResult` to `DialogResult.Cancel` before closing the form in your Cancel button handler. – itsme86 Jun 08 '20 at 14:54
  • I am new in winforms. I can't understant where to set it. Can you write it, please? – Alex Jun 08 '20 at 15:03
  • 1
    you just add `this.DialogResult = DialogResult.Cancel` in your btCancel_Click method – JonasH Jun 08 '20 at 15:06
  • I think you mean this if(this.DialogResult==DialogResult.Cancel) { Close(); } But it is not working. – Alex Jun 08 '20 at 15:07
  • No, I mean what @JonasH said. Put that code on the line above your `Close();` line in your `btnCancel_Click()` method. – itsme86 Jun 08 '20 at 15:24
  • it is not working like this private void btCancel_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; Close(); } – Alex Jun 08 '20 at 15:30
  • Remove the Button.Click handler. Buttons have a `DialogResult` property, plus the Form has the `AcceptButton` and `CancelButton` properties that you have to set. These determine the DialogResult value. You don't need anything else. – Jimi Jun 08 '20 at 15:47
  • When I deleted the handler. I can type in the First name text box and it shows in the main form simultaneously. I think the data source biding uses textbox textchanged event and changes it when I write anything in any text box. – Alex Jun 08 '20 at 16:04
  • See the simple method shown here: [Binding a TextBox to a ListBox SelectedItem](https://stackoverflow.com/a/57235083/7444103). BTW, why did you disable VisualStyles? Your Forms seem to come straight from the Jurassic. – Jimi Jun 08 '20 at 16:20
  • Sorry Jimi it is our teacher showed us. – Alex Jun 08 '20 at 16:24

2 Answers2

0

I think you can either set the DialogResult property of your cancel button to Cancel in Properties window or you can add this.DialogResult = DialogResult.Cancel before the Close() on your btCancel_Click event.

Ramin
  • 19
  • 5
  • You don't even need to call `Close()`, setting `DialogResult` to any value will close the form and continue with the evaluation of the `ShowDialog()` call – Ivan García Topete Jun 08 '20 at 16:47
0

The Problem is that you put the Databinding directly onto the Employee object of the underlying list. The cancel button closes just the Form. Right now you implemented nothing in order to revert your changes.

I would suggest the following:

public partial class FormEdit : Form
{
    Employee employee;
    Employee employeeWorkingCopy;
    BindingSource bs = new BindingSource(); 

    public FormEdit(Employee employee)
    {
        InitializeComponent();
        this.employee = employee;
        this.employeeWorkingCopy = new Employee();
        this.employeeWorkingCopy.TakeValuesFrom(employee);

        bs.DataSource = this.employeeWorkingCopy;
        tbFirstName.DataBindings.Add("Text", bs, "FirstName", false, DataSourceUpdateMode.OnPropertyChanged);
        tbLastName.DataBindings.Add("Text", bs, "LastName", false, DataSourceUpdateMode.OnPropertyChanged);
        tbInn.DataBindings.Add("Text", bs, "INN", false, DataSourceUpdateMode.OnPropertyChanged);
        dtmBirthday.DataBindings.Add("Value", bs,"Birthday",
            false, DataSourceUpdateMode.OnPropertyChanged);
    }

    private void btCancel_Click(object sender, EventArgs e)
    {
        Close();
    }

    private void btnOK_Click(object sender, EventArgs e)
    {
        this.employee.TakeValuesFrom(this.employeeWorkingCopy);
        Close();
    }
}

And in your Employee class:

public class Employee {
     // ... the other stuff of that class

     public void TakeValuesFrom(Employee other)
     {
         this.FirstName = other.FirstName;
         this.LastName = other.LastName;
         this.INN = other.INN;
         this.Birthday = other.Birthday;
     }
}

By that the edit dialog operates on a copy of the original Employee object and only when the user clicks ok, the values are copied back to the original object.

You can do it also the other way round: work on the original object and keep a copy to revert to the original values in case the user clicks the cancel button. But that might lead to undesired side effects since it seems that you are using the original objects also directly in the parent dialog.

Torben Schramme
  • 2,104
  • 1
  • 16
  • 28