RE: Binding custom list of usercontrols?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Hi Andy,

Based on my understanding, you bind a container control, e.g. a Panel to a
collection and want the Panel to create a UserControl for each business
object in the collection. You set up data binding between the UserControl
and the corresponding business object. If you add an item in the
collection, a new UserControl should be added in the Panel; if you remove
an item in the collection, the corresponding UserControl should be removed
as well. If you make a change in one business object within the collection,
the corresponding UserControl should update immediately. If I'm off base,
please feel free to let me know.

Firstly, when a list implements the IBindingList interface, it supports
change notifications, both for when the list items change (for example, the
third item in a list of customers has a change to the Address field), as
well as when the list itself changes (for example, the number of items in
the list increases or decreases).

NET Framework has provided the BindingList<T> class which implements the
IBindingList interface. I suggest you to use the BindingList<T> as the type
of the list.

Secondly, objects contained within the list will have to notify the list
when they change so that the list can raise the ListChanged event. Only if
an object implements the INotifyPropertyChanged interface, it will raise an
event when any of its property values change so that the list is notified.

To get what you want, you could write a public method in the derived Panel
class to accept a list and create a UserControl for each item in the list.

I will illustrate this with an example. Let's say I have custom class
Person with a property called Name of type string and a derived Panel. When
I assign a list of Person objects to the derived Panel, a TextBox is
created for each item in the list and the Text property of each TextBox is
bound to the Name property of the corresponding Person object. If I
add/remove items in the list, the TexBoxes in the derived Panel are
added/removed; if I change the value of the Name property of one Person
object in the list, the displayed text is updated in the corresponding
TextBox.

The following is the sample code.

class MyPanel:Panel
{
private IBindingList datasource = null;
public void SetDataSource(IBindingList objs)
{
if (datasource != null && datasource != objs)
{
datasource.ListChanged -= new
ListChangedEventHandler(datasource_ListChanged);
this.Controls.Clear();
}
datasource = objs;
datasource.ListChanged += new
ListChangedEventHandler(datasource_ListChanged);
TextBox txtbox = null;
for (int i = 0; i < datasource.Count; i++)
{
txtbox = new TextBox();
txtbox.Tag = datasource[i];
txtbox.DataBindings.Add(new Binding("Text", datasource[i],
"Name"));
this.Controls.Add(txtbox);
}
this.RearrangeTextBoxes();
}

void datasource_ListChanged(object sender, ListChangedEventArgs e)
{
if (e.ListChangedType == ListChangedType.ItemAdded)
{
TextBox txtbox = new TextBox();
txtbox.Tag = datasource[e.NewIndex];

txtbox.DataBindings.Add(new Binding("Text",
datasource[e.NewIndex], "Name"));
this.Controls.Add(txtbox);

this.RearrangeTextBoxes();
}
else if (e.ListChangedType == ListChangedType.ItemDeleted)
{
foreach (TextBox ctrl in this.Controls)
{
if (!datasource.Contains(ctrl.Tag))
{
this.Controls.Remove(ctrl);
break;
}
}
this.RearrangeTextBoxes();
}
}

private void RearrangeTextBoxes()
{
for (int i = 0; i < this.Controls.Count; i++)
{
this.Controls[i].Top = i * (this.Controls[i].Height + 5);
}
}
}

class Person : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
if (value != name)
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
public Person(string name)
{
this.name = name;
}

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

private PropertyChangedEventHandler propertychanged;

#region INotifyPropertyChanged Members

event PropertyChangedEventHandler
INotifyPropertyChanged.PropertyChanged
{
add { propertychanged += value; }
remove { propertychanged -= value; }
}

#endregion
}

// test code
public partial class Form1 : Form
{
BindingList<Person> persons;
private void Form1_Load(object sender, EventArgs e)
{
persons = new BindingList<Person>();
persons.Add(new Person("1"));
persons.Add(new Person("2"));

this.myPanel1.SetDataSource(persons);

}

private void button1_Click(object sender, EventArgs e)
{
persons.Add(new Person("3"));
persons[0].Name = "new value";
}

private void button2_Click(object sender, EventArgs e)
{
persons.RemoveAt(0);
}
}

Hope this helps.
If you have any question, please feel free to let me know.


Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

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

.



Relevant Pages

  • RE: Cant update foreground panel from background thread
    ... you cannot update a control from a thread that did not create the control. ... In your case you are adding the labels to the panel from a different thread ... void private void backgroundWorker1_DoWork ... Label label1 = new Label; ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Cant select Item in a list box
    ... I'll implement your suggestions with the panel. ... >> is cause I'll be using the same class for other usercontrol ... > Personally I like this way of control creation because it allows for a ... > demand then at the users request you can just remove all the children from ...
    (microsoft.public.dotnet.framework.windowsforms.controls)
  • Re: New House Alarm - Am I locked out?
    ... or previous monitoring contracts. ... They may very well be able to dial into the panel remotely and unlock ... complaint with the Better Business Bureau. ... their old house as part of a "guaranteed sale" program so they no ...
    (alt.security.alarms)
  • Re: New House Alarm - Am I locked out?
    ... or previous monitoring contracts. ... They may very well be able to dial into the panel remotely and unlock ... complaint with the Better Business Bureau. ... their old house as part of a "guaranteed sale" program so they no ...
    (alt.security.alarms)
  • Re: New House Alarm - Am I locked out?
    ... or previous monitoring contracts. ... They may very well be able to dial into the panel remotely and unlock ... complaint with the Better Business Bureau. ... their old house as part of a "guaranteed sale" program so they no ...
    (alt.security.alarms)