data binding questions

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

Guest

Hi,
I have experience with windowsforms but not with data binding. Before I take
up with the subject I would like to ask some questions just to make sure I am
on the right path:

A data source (array or similar) is bound to a datagridview.

If I change from GUI the value inone of the cells, will the value in the
data source change without me writing code (trapping keystrokes etc.) ?

If I change the value in the array programatically or from another place in
GUI, will the datagridview update its corresponding cell?

I suspect the answer to both questions is affirmative, just want to make sure

Thank you
 
Hi Z,

Yes, that is the goal of the binding. The code below illustrates this by setting a list of MyClass object as DataSource in a DataGridView. Theeffect is all properties in MyClass will be bound its own column in theDataGridView. Changing a value in the grid will change the underlying source, which is demonstrated with a Button.Click event.

The code assumes you have a DataGridView called DataGridView1 and a Button called button1 on the form

public partial class Form1 : Form
{
private List<MyClass> strings = new List<MyClass>();
public Form1()
{
InitializeComponent();
strings.Add(new MyClass("Hello"));
strings.Add(new MyClass("World"));
dataGridView1.DataSource = strings;
}

private class MyClass
{
string s;
public string Text
{
get { return s; }
set { s = value; }
}

public MyClass(string s)
{
Text = s;
}
}

private void button1_Click(object sender, EventArgs e)
{
string s = "";
foreach (MyClass c in strings)
s += c.Text + Environment.NewLine;

MessageBox.Show(s);
}
}
 
You need to have your data carrier class implement INotifyPropertyChanged or
provide a <property>Changed event for each of the properties exposed.

Failure to do this will have the data update in one binding scenarion but
changes won't be seen if the object is bound to two objects such as in a
master-detail view.

--
--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.


Hi Z,

Yes, that is the goal of the binding. The code below illustrates this by
setting a list of MyClass object as DataSource in a DataGridView. The
effect is all properties in MyClass will be bound its own column in the
DataGridView. Changing a value in the grid will change the underlying
source, which is demonstrated with a Button.Click event.

The code assumes you have a DataGridView called DataGridView1 and a Button
called button1 on the form

public partial class Form1 : Form
{
private List<MyClass> strings = new List<MyClass>();
public Form1()
{
InitializeComponent();
strings.Add(new MyClass("Hello"));
strings.Add(new MyClass("World"));
dataGridView1.DataSource = strings;
}

private class MyClass
{
string s;
public string Text
{
get { return s; }
set { s = value; }
}

public MyClass(string s)
{
Text = s;
}
}

private void button1_Click(object sender, EventArgs e)
{
string s = "";
foreach (MyClass c in strings)
s += c.Text + Environment.NewLine;

MessageBox.Show(s);
}
}
 
You need to have your data carrier class implement INotifyPropertyChanged or
provide a <property>Changed event for each of the properties exposed.

Failure to do this will have the data update in one binding scenarion but
changes won't be seen if the object is bound to two objects such as ina
master-detail view.

Well, you can do without INotifyPropertyChanged in many cases, but anything other than simply DataBinding cases you will have to notify the controls of a change in the underlying source (or vice versa if you want to get notified of all changes or just validated changes).

A modified version of the previous code sample has a new Button (button2) and a TextBox (textBox1) added. Clicking button2 will change the second MyObject's Text property in code.

Instead of binding the grid directly to the object list, dataGridView1 is now bound to a BindingSource containing the list. The BindingSource can then keep track of the selected row in the grid and use this information to display details in other controls. Not to mention how easy it isto add new items in the grid by setting BindingSource.AllowNew (note, this requires a dynamic list as well as a default constructor in the object) The sample uses a single property "Text" displayed in the grid and the TextBox, but the TextBox could just as well be bound to properties not displayed in the grid.

Notice the commented line in the setter in the Text property. This calls NotifyPropertyChanged which is a method firing the PropertyChanged event telling all the controls bound to this property to update the view. To see the effect, select the second row in the grid and click button2 with and without the line commented out. If the control isn't notified, the data is still changed, but it won't be displayed until the data is normally read (like selecting the row again). You may also notice that if the row isn't selected, the grid isn't updated either, even if it is notified. I don't remember exactly why, but the BindingSource doesn't appear to keep track of nonselected members.

public partial class Form1 : Form
{
private List<MyClass> strings = new List<MyClass>();
public Form1()
{
InitializeComponent();
strings.Add(new MyClass("Hello"));
strings.Add(new MyClass("World"));

BindingSource s = new BindingSource(strings, "");
s.AllowNew = true; // Lets us add new items in the grid

dataGridView1.DataSource = s;
textBox1.DataBindings.Add("Text", s, "Text");
}

private class MyClass : INotifyPropertyChanged
{
string s;
public string Text
{
get { return s; }
set
{
s = value;
// Uncomment the line below
//NotifyPropertyChanged("Text");
}
}

// Default constructor needed to add new items in the grid
public MyClass() { }

public MyClass(string s)
{
Text = s;
}

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string property)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}

private void button1_Click(object sender, EventArgs e)
{
string s = "";
foreach (MyClass c in strings)
s += c.Text + Environment.NewLine;

MessageBox.Show(s);
}

private void button2_Click(object sender, EventArgs e)
{
strings[1].Text = "Night";
}
}
 
Back
Top