Stumped by bound controls

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

I'm having trouble getting control data binding to work. As I understand
it, the simplest form of databinding requires three things:

1) A control (say a textbox) on a form or user control,
2) A field or object.member to which you want to bind,
3) A "Binding" object that connects the variable to a property of the
control ("Text" for example).

The example that follows does these three things, but the data binding
doesn't work (at least not like it think it should). It couldn't be simpler.
I have a form with two textboxes. One is "bound" to the field myInt. The
other has it's "Text" property set to myInt.ToString() each time myInt
changes. myInt starts with a value of 200. There is a button on the form
that increments myInt.

Now I expect that the value displayed should stay in synch between the two
textboxes. But, although they start in synch (both showing "200"),
incrementing myInt by clicking the button changes the value in the textbox
that has "Text" explicitly changed, but my bound textbox continues to display
"200".

I'm obviously missing something very basic here.

Thanks.

BBM

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace BPDescriptorTests
{
/// <summary>
/// Summary description for BoundForm.
/// </summary>
public class BoundForm : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
public int myInt = 200;
private System.Windows.Forms.TextBox textBox2;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public BoundForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
this.textBox2.Text = myInt.ToString();
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
// This stuff looked standard so I omitted it... BBM
#endregion

static void Main()
{
Application.Run(new BoundForm());
}

private void button1_Click(object sender, System.EventArgs e)
{
myInt ++;
this.textBox2.Text = myInt.ToString();
}

private void BoundForm_Load(object sender, System.EventArgs e)
{
this.textBox1.DataBindings.Add("Text",myInt,null);
}
}
}
 
I've not done a lot with ADO.Net and bound objects, but I
can tell you that in VB-6 and before you needed to have
a "data control" also. This supplied the cursor to allow
access to single records and you then bound to individula
columns in bound controls. Check the ADO models, I think
you'll find a similar requirement.
 
Hi BBM,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that when you bind a textbox to a int
variable. If there is any misunderstanding, please feel free to let me know.

This doesn't work, because int is a value type. The int object is on the
function stack. When you add a a data binding to the control, it is
actually binding to a copy of the original int. So when your int increases,
the text of TextBox doesn't change. So my recommendation is to set
TextBox.Text property again each time your int changes. It is the simplest
way.

HTH.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Kevin,

Thanks for your response. I see how DataBinding.Add used a "boxed" copy of
the real int. However...

My "real" requirement is to bind textbox.Text to a data member of an object.
I'd like to bind Obj.Id, an int property of the object to the textbox "Text"
property. I've tried this a bunch of different ways, including binding to
"string" versions of integer properties (Obj.IdString for example that does
all the necessary conversions).

So I haven't been able to get it to work whether I bound to a value type or
a reference type. I've tried it using two parms of the DataBindings.Add
method ("Text", Obj.IdStr, null) and all three parms ("Text", Obj, "IdStr").

Attached is a slightly changed version of my original example. I have added
a very simple object, and attempt to bind the first textbox to a string
property of the object. It doesn't work.

Of course I could explicitly set the values of controls for every object
attribute but I thought that databinding was supposed to do this without
having to write all that code.

Thanks.

BBM

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace BPDescriptorTests
{
public class Person
{
int id;
string name;
public int Id
{
get{ return id;}
set{id = value;}
}
public string IdStr
{
get{ return id.ToString();}
set{ id = System.Convert.ToInt32(value);}
}
public Person(int i, string n)
{
id = i;
name = n;
}

}
/// <summary>
/// Summary description for BoundForm.
/// </summary>
public class BoundForm : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
public int myInt = 200;
public Person p;
private System.Windows.Forms.TextBox textBox2;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public BoundForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
p = new Person(200, "George Bush");
this.textBox2.Text = p.IdStr;
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
// Removed this stuff... BBM
#endregion

static void Main()
{
Application.Run(new BoundForm());
}

private void button1_Click(object sender, System.EventArgs e)
{
int i;
i = p.Id + 1;
p.IdStr = System.Convert.ToString(i);

this.textBox2.Text = p.IdStr;
}

private void BoundForm_Load(object sender, System.EventArgs e)
{
textBox1.DataBindings.Add("Text",p,"IdStr");
}
}
}
 
aaa,

Thanks for your response. Yes, that's exactly what was wrong. I
implemented the
<propertyname> changed event and got it to work.

The book C# Business Objects says that what I was trying will work as long
as the value of the property is not changed in CODE. To catch this you have
to use the "changed" event.

Also thanks for the reference to the dotnet247.com discussion site I think
I'll give it a try the next time I have a problem.

Thanks again.

BBM
 
Back
Top