views:

209

answers:

2
public partial class Form1 : Form
{
    MyClass myClass = new MyClass("one", "two");

    public Form1()
    {
        InitializeComponent();
        textBox1.DataBindings.Add("Text", myClass, "Text1", false, DataSourceUpdateMode.Never);
        textBox2.DataBindings.Add("Text", myClass, "Text2", false, DataSourceUpdateMode.Never);
    }

    private void saveButton_Click(object sender, EventArgs e)
    {
        myClass.Text1 = textBox1.Text;
        myClass.Text2 = textBox2.Text;
        //textBox1.DataBindings["Text"].WriteValue();
        //textBox2.DataBindings["Text"].WriteValue();
    }
}

public class MyClass : INotifyPropertyChanged
{
    private string _Text1;
    private string _Text2;

    public event PropertyChangedEventHandler PropertyChanged;

    public string Text1
    {
        get { return _Text1; }
        set { _Text1 = value; OnPropertyChanged(new PropertyChangedEventArgs("Text1")); }
    }

    public string Text2
    {
        get { return _Text2; }
        set { _Text2 = value; OnPropertyChanged(new PropertyChangedEventArgs("Text2")); }
    }

    public MyClass(string text1, string text2)
    {
        Text1 = text1;
        Text2 = text2;
    }

    protected void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null) PropertyChanged(this, e);
    }
}

I think is pretty clear what I'm trying to achieve. I want my form to save the changes made in my two TextBoxes to myClass. But whenever I press the save button after editing both text boxes, and saveButton_Click is invoked, the second textBox2's Text goes back to the original text ("two"). I tried using Binding's WriteValue function but the same thing happens. Using .net 4.0.

Edit Thanks for your answers, but I don't need workarounds. I can find them myself. I just need to understand a little bit better how binding works. I would like to understand why is this happening?

+1  A: 

You need to change the way you are doing your data binding. Try this.

MyClass myClass = new MyClass("one", "two");

public Form1()
{
    InitializeComponent();
    textBox1.DataBindings.Add("Text", myClass, "Text1", false, DataSourceUpdateMode.OnPropertyChanged);
    textBox2.DataBindings.Add("Text", myClass, "Text2", false, DataSourceUpdateMode.OnPropertyChanged);
}

private void saveButton_Click(object sender, EventArgs e)
{
    // your object should already have new text values entered.
    // Save your object!

    //myClass.Text1 = textBox1.Text;
    //myClass.Text2 = textBox2.Text;
    //textBox1.DataBindings["Text"].WriteValue();
    //textBox2.DataBindings["Text"].WriteValue();
}

The key is the DataSourceUpdateMode, this will allow the text property of the textbox to cascade into your custom object whenever the property changes. I hope this helps.

[Edit]

I believe what you need to do to achieve what you're asking for is this: TextBox1.DataBindings[0].ControlUpdateMode = ControlUpdateMode.Never This link should provide some additional information.

James
But I don't want the data to be saved when the `TextBox`'s `Text` changes, I want it to change when the save Button is pressed. How can I do that? Isn't `DataSourceUpdateMode.Never` together with `WriteValue()` intended to achieve this kind of functionality?
jsoldi
Don't use databindings. Just manually assign the text values in the forms constructor to the textboxes, like this: `textBox1.Text = myClass.Text1;`
James
@jsoldi - then don't use data binding for those values - set the values in the saveButton_Click event. That is what databinding is for - it binds the properties of the control instances to the properties of the data object.
JeremyDWill
I tried that. But I want that if I have to windows editing the same `MyClass` object and one saves changes, the other automatically updates. I can find a workaround, like saving `textBox2.Text` in a temporary string and then assign it in the `saveButton_Click` but my question really is why is this happening? Is it __supposed__ to be that way?
jsoldi
Yes that is the way data-binding works out of the box. Take a look at my last edit, this should achieve what you're after.
James
+3  A: 

Apparently, updating any value on the data source will cause all bindings to be updated. This explains the behavior (setting myClass.Text1 causes textBox2 to be updated with the current value of myClass.Text2). Unfortunately, the few posts I was able to find pretty much just said, "that's how it works".

One way to handle this is to create a BindingSource, set BindingSource.DataSource = myClass, and then bind your TextBoxes to the BindingSource.

BindingSource raises ListChanged events if the underlying data source is a list and items are added, removed, etc., or if the DataSource properties change. You can suppress these events by setting BindingSource.RaiseListChangedEvents to false, which would let you set multiple properties on myClass without data-binding updating the bound controls.

public partial class Form1 : Form
{
    MyClass myClass = new MyClass("one", "two");
    BindingSource bindingSource = new BindingSource();

    public Form1()
    {
        InitializeComponent();

        bindingSource.DataSource = myClass;

        textBox1.DataBindings.Add("Text", bindingSource, "Text1", true, DataSourceUpdateMode.Never);
        textBox2.DataBindings.Add("Text", bindingSource, "Text2", true, DataSourceUpdateMode.Never);                
    }

    private void button1_Click(object sender, EventArgs e)
    {
        bindingSource.RaiseListChangedEvents = false;
        myClass.Text1 = textBox1.Text;
        myClass.Text2 = textBox2.Text;
        bindingSource.RaiseListChangedEvents = true;
    }
}

HTH

adrift
That worked. But I don't understand why if my properties are not part of a list.
jsoldi
@jsoldi, I edited my answer to include the fact that `ListChanged` is also raised when the `DataSource` properties change.
adrift