Binding control property to class property?

  • Thread starter Johnny Jörgensen
  • Start date
J

Johnny Jörgensen

Can anybody help me with this problem, please:


I've got a class

public MyClass
{
private string m_TextValue = "";

public void SetValues()
{
m_TextValue = "Test";
}

public string TextValue
{
get { return m_TextValue; }
set { m_TextValue = value; }
}
}

and in a form I instatiate my class

private MyClass MyClassInstance = new MyClass();

I bind the TextValue property of MyClassInstance to a Textbox' Text field in
the Form_Load event:

textBox1.DataBindings.Add("Text", MyClassInstance, "TextValue");

(I can also do this using the DataBindings field in the Property editor, but
that doesn't change anything)

I would expect textbox1 to show "" now (which it does).

Then I call:
MyClassInstance.SetValues();

Then I would expect textBox1 to show "Test" (which it DOESN'T!)

But if I enter text into textBox1, it is correctly transferred to the
MyClassInstance.TextValue property, so I know the databinding works. What I
don't understand is why the SetValues method changes doesn't reflect in the
bound control's property.

What am I missing?

TIA,
Johnny Jörgensen
 
M

Marc Gravell

How would the UI know about the change? You need to implement change
notification. There are 2 *primary* ways of doing this (and various
others);

a: (property specific notification)
add a notification event as follows:
public event EventHandler TextValueChanged;
change your setter to:
set {
if(value == m_TextValue) return; // do nothing if not changed
m_TextValue = value;
EventHandler handler = TextValueChanged;
if(handler!=null) handler(this, EventArgs.Empty); // notify callers
(if any)
}

[although the norm is to split out the bottom 2 into an On... method]

b: (shared notification)
implement the INotifyPropertyChanged, and simlar to above but instead
of EventArgs.Empty you'd create a new
PropertyChangedEventArgs("TextValue")

Marc
 
M

Marc Gravell

Note... if you use the first approach and you have more than a couple
of events you may wish to look into EventHandlerList; this reduces the
footprint as the class only reserves space for one reference field per
instance and one static reference key per event, not one per event per
instance

(i.e. when nothing is listening your placeholders consume "instances +
events" space instead of "instances * events" space).

Marc
 
J

Johnny Jörgensen

Thanks Marc

I tried using approach b because I have a lot of properties.

I changed:
public class MyClass
to
public class MyClass : INotifyPropertyChanged

and added:

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}

Then I changed the Set's to:

public string TextValue
{
get { return m_TextValue; }
set
{
if (value == m_TextValue) { return; }
m_TextValue = value;
NotifyPropertyChanged("TextValue");
}
}

But still it doesn't work. What am I missing this time?

TIA,
Johnny J.
 
M

Marc Gravell

A very simple oversight; SetValues should read:
TextValue = "Test"
- otherwise none of your fancy new code will ever get called. I have
tested this (below) and it works fine. As a general rule, try to only
talk to fields from property getters/setters (and constructors if
marked readonly) - that way you can't miss this type of thing. Don't
worry about performance: if the getter etc is simple then it will get
inlined by the JIT anyway.

static void Main() {
MyClass c = new MyClass();
using (Form f = new Form())
using (Button b = new Button()) {
f.Controls.Add(b);
f.DataBindings.Add("Text", c, "TextValue");
b.Click += delegate {
c.SetValues();
};
f.ShowDialog();
}
}

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top