|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Binding Manually for Sanity's sake - How to do it intelligentlyWe 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 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); } } } On Nov 26, 1:58 pm, Marc Gravell <marc.grav***@gmail.com> wrote:
Show quote > Well, you can use automatic binding for most properties (including Our problem is when we move over a BindingList. it seems to not> 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 - repopulate the textbox when moving to the next record. It is like it is only bound to a single record. > Our problem is when we move over a BindingList. That sounds like a currency issue. Have you bound the differentcontrols 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 Am Mon, 26 Nov 2007 11:44:57 -0800 (PST) schrieb jehugalea***@gmail.com:
> Hello: Note that databinding is not type safe. > > We are working on a large number of forms. [rest snipped] 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 > Note that databinding is not type safe. Very, very true. Oh, for a very simple solution that has been> ...NOT for the strings you use for databinds. 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 |
|||||||||||||||||||||||