views:

4405

answers:

5

Objective-c/cocoa offers a form of binding where a control's properties (ie text in a textbox) can be bound to the property of an object. I am trying to duplicate this functionality in C# w/ .Net 3.5.

I have created the following very simple class in the file MyClass.cs:

class MyClass
{
    private string myName;

    public string MyName
    {
        get
        {
            return myName;
        }

        set
        {
            myName = value;
        }
    }

    public MyClass()
    {
        myName = "Allen";
    }
}

I also created a simple form with 1 textbox and 1 button. I init'd one instance of Myclass inside the form code and built the project. Using the DataSource Wizard in Vs2008, i selected to create a data source based on object, and selected the MyClass assembly. This created a datasource entity. I changed the databinding of the textbox to this datasource; however, the expected result (that the textbox's contents would be "allen") was not achieved. Further, putting text into the textbox is not updating the name property of the object.

I know i'm missing something fundamental here. At some point i should have to tie my instance of the MyClass class that i initialized inside the form code to the textbox, but that hasn't occurred. Everything i've looked at online seems to gloss over using DataBinding with an object (or i'm missing the mark entirely), so any help is great appreciated.

----Edit--- Utilizing what i learned by the answers, i looked at the code generated by Visual Studio, it had the following: this.myClassBindingSource.DataSource = typeof(BindingTest.MyClass);

if i comment that out and substitute : this.myClassBindingSource.DataSource = new MyClass();

i get the expected behavior. Why is the default code generated by VS like it is? Assuming this is more correct than the method that works, how should i modify my code to work within the bounds of what VS generated?

+2  A: 

You should implement the INotifyPropertyChanged interface to your MyClass type:

public class MyClass : INotifyPropertyChanged
{
   private string _myName;

   public string MyName
   {
       get { return _myName; }
       set
       {
          if( _myName != value )
          {
              _myName = value;
              OnPropertyChanged("MyName");
          }
       }
   }

   public event PropertyChangedEventHandler PropertyChanged;

   private void OnPropertyChanged(string propertyName)
   {
       if( PropertyChanged != null )
           PropertyChanged( this , new PropertyChangedEventArgs(propertyName) );
   }       
}

This interface is required for the DataBinding infrastructure if you want to support simple databinding. The INotifyPropertyChanged interface is used to notify a 'binding' that a property has changed, so the DataBinding infrastructure can act accordingly to it.

Then, you can databind the MyName property to the Text Property of the textbox.

Frederik Gheysels
A: 

Looks like you probably need a Bindable attribute on your MyName property (and follow Frederik's suggestion as well):

   [System.ComponentModel.Bindable(true)] 
   public string MyName
   {
       get { return _myName; }
       set
       {
          if( _myName != value )
          {
              _myName = value;
              OnPropertyChanged("MyName");
          }
       }
   }

Via: http://support.microsoft.com/kb/327413

Cory Larson
A: 

I don't have any code in front of me, but I think the data source is kind of like a collection. You have to add an instance of MyClass to the data source, and that's what the form fields will bind to. There's also methods for navigating through the data source to multiple instances of MyClass, but it doesn't sound like you need that. Check the docs for DataSource.

I don't think you need to implement any fancy interfaces. I seem to remember there's a method on the data source that lets you refresh or rebind the current item after you change some values.

Don Kirkby
+2  A: 

You must assign the textbox's data source to be your new datasource. But additionally, you must assign the datasource's datasource to be an instance of your class.

MyDataSource.DataSource = new MyClass();
TextBox1.DataSource = MyDataSource;

That should work for your first pass. As others have mentioned, you may need to implement additional interfaces on your class (INotifyPropertyChanged etc), if you are going to be modifying the class properties via any background processes.

If you are only updating the properties via the form, then you do not need this step.

Jason Coyne
TextBox1.DataBindings.Add("Text", >Your Object<, ">PropertyName<");
Gerben Limburg
A: 

GET ERROR MESSAGE IN THE DataBinding.ADD("TEXT", myObject, myObjectProperty) method??

This is probably because you're missing the explicit {get;set;} on the property declaration!

BAD: public string FirstName; <-- you will not be able to bind to this property!

GOOD: public string FirstName { get; set; }

Ron Maman