Binding Manually for Sanity's sake - How to do it intelligently

J

jehugaleahsa

Hello:

We are working on a large number of forms. The original approach was
to use the built-in data designer, type-specific DataTables and form
binding. However, we are running into various issues due to the
complexity of our forms. For instance, how do you bind to a check box
with a data table, or a radio group?

Well, I have since started making business objects that wrap around
DataRows. The business objects simply provide properties that wrap
around the DataRow data and return it in a desired format.

To maintain all my business objects, I am creating a
BindingList<MyBO>. Doing this really is frustrating since it means I
have to handle the BindingList<MyBO>.AddingNew event. Also, when I am
navigating with a DataNavigator control, I have to manually rebind all
my controls.

So I am holding a reference to a DataTable, BindingList<MyBO> and a
BindingSource that controls the BindingList. It is really confusing.
It can't be this confusing to use business objects in Windows Forms.
What am I missing that will help simplify this new approach?

Thanks for any pointers,
Travis
 
M

Marc Gravell

Well, you can use automatic binding for most properties (including
check-box). The radio is an exception perhaps. Is there a specific
binding issue you are trying to avoid?

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

public class Person : INotifyPropertyChanged
{
private string name;
private DateTime dateOfBirth = DateTime.Today;
private bool isActive;
public string Name {
get {return name;}
set {SetField(ref name, value, "Name");}
}
public bool IsActive
{
get { return isActive; }
set { SetField(ref isActive, value, "IsActive"); }
}
public DateTime DateOfBirth {
get {return dateOfBirth;}
set {SetField(ref dateOfBirth, value, "DateOfBirth");}
}
public Person() { }
public Person(string name, DateTime dateOfBirth, bool isActive) {
Name = name; DateOfBirth = dateOfBirth; IsActive = isActive;
}
protected void SetField<T>(ref T field, T value, string
propertyName)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{ // changed
field = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(propertyName));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
static class Program
{

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
BindingList<Person> people = new BindingList<Person>();
people.Add(new Person("Fred",
DateTime.Today.AddYears(-20),true));
people.Add(new Person("Wilma",
DateTime.Today.AddYears(-25),false));
BindingSource bs = new BindingSource(people, "");
bs.DataError += delegate { };
using (Form f = new Form())
{
DataGridView dgv = new DataGridView();
dgv.DataSource = bs;
CheckBox cb = new CheckBox();
cb.DataBindings.Add("Checked", bs, "IsActive");
TextBox tb = new TextBox();
tb.DataBindings.Add("Text", bs, "Name");
DateTimePicker dtp = new DateTimePicker();
dtp.DataBindings.Add("Value", bs, "DateOfBirth");

cb.Dock = tb.Dock = dtp.Dock = dgv.Dock = DockStyle.Top;
f.Controls.AddRange(new Control[] { cb, tb, dtp, dgv });
Application.Run(f);

}

}
}
 
J

jehugaleahsa

Well, you can use automatic binding for most properties (including
check-box). The radio is an exception perhaps. Is there a specific
binding issue you are trying to avoid?

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

public class Person : INotifyPropertyChanged
{
private string name;
private DateTime dateOfBirth = DateTime.Today;
private bool isActive;
public string Name {
get {return name;}
set {SetField(ref name, value, "Name");}
}
public bool IsActive
{
get { return isActive; }
set { SetField(ref isActive, value, "IsActive"); }
}
public DateTime DateOfBirth {
get {return dateOfBirth;}
set {SetField(ref dateOfBirth, value, "DateOfBirth");}
}
public Person() { }
public Person(string name, DateTime dateOfBirth, bool isActive) {
Name = name; DateOfBirth = dateOfBirth; IsActive = isActive;
}
protected void SetField<T>(ref T field, T value, string
propertyName)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{ // changed
field = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(propertyName));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;}

static class Program
{

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
BindingList<Person> people = new BindingList<Person>();
people.Add(new Person("Fred",
DateTime.Today.AddYears(-20),true));
people.Add(new Person("Wilma",
DateTime.Today.AddYears(-25),false));
BindingSource bs = new BindingSource(people, "");
bs.DataError += delegate { };
using (Form f = new Form())
{
DataGridView dgv = new DataGridView();
dgv.DataSource = bs;
CheckBox cb = new CheckBox();
cb.DataBindings.Add("Checked", bs, "IsActive");
TextBox tb = new TextBox();
tb.DataBindings.Add("Text", bs, "Name");
DateTimePicker dtp = new DateTimePicker();
dtp.DataBindings.Add("Value", bs, "DateOfBirth");

cb.Dock = tb.Dock = dtp.Dock = dgv.Dock = DockStyle.Top;
f.Controls.AddRange(new Control[] { cb, tb, dtp, dgv });
Application.Run(f);

}

}



}- Hide quoted text -

- Show quoted text -

Our problem is when we move over a BindingList. it seems to not
repopulate the textbox when moving to the next record. It is like it
is only bound to a single record.
 
M

Marc Gravell

Our problem is when we move over a BindingList.

That sounds like a currency issue. Have you bound the different
controls to the same view of the data? This is necessary for them to
share a CurrencyManager. My example above demonstrates this working
just fine, updating the Name textbox (in my case I've wrapped with a
BindingSource for convenience) - so what is happening differently? How
(to which source objects) are you doing your various bindings?

Marc
 
P

Paul Werkowitz

Am Mon, 26 Nov 2007 11:44:57 -0800 (PST) schrieb (e-mail address removed):
Hello:

We are working on a large number of forms.
[rest snipped]

Note that databinding is not type safe.

When developing a large program you always have to do some sort of
refactoring over time. VS makes this easy - but only for known names, i.e.
program entities. NOT for the strings you use for databinds. The result?
Your program will compile, but will behave differently. Usually you don't
even get a error message *at runtime* . Your chances to get such errors are
low. Probably your customers are the first to find them....

IMHO databinding is completely unusable for larger programs.

Greetz
Paule
 
M

Marc Gravell

Note that databinding is not type safe.
...NOT for the strings you use for databinds.

Very, very true. Oh, for a very simple solution that has been
discussed here (to death) before; a new
"nameof(SomeType.SomeAccessibleMember)" compile-time operator, which
might evaulate to a string but get checked at compile-time. Presumably
it would be very easy to implement, and invaluable to data-binding.

Oh well, we live with what we have...

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