I'm using winforms and I've got a comboBox that represents an IQueryable. Below the combobox is a series of textboxes that I would like to be bound to the currently selected from the combo box.
Here is my code.
public partial class TestForm : Form
{
public DataClassesDataContext DataContext;
public IQueryable<T> datasource;
// Ctor
public TestForm()
{
InitializeComponent();
// L2S data context
this.DataContext = new DataClassesDataContext();
// Get the variable for the data source
this.datasource = this.DataContext.Ts;
// setup the binding for the combobox
this.comboBox1.DataSource = this.datasource;
this.comboBox1.DisplayMember = "Description";
this.comboBox1.ValueMember = "Id";
// assign the databindings of the text boxes to the selectedItem of the combo box
// this is where the problem is, afaik
TId.DataBindings.Add(new Binding("Text", this.comboBox1.SelectedItem, "Id"));
TUser.DataBindings.Add(new Binding("Text", this.comboBox1.SelectedItem, "User"));
TDescription.DataBindings.Add(new Binding("Text", this.comboBox1.SelectedItem, "Description"));
}
Doing this binds everything, When I change the values in the text boxes, it updates the initially selected item in the combo box just fine. Even when I change the description, it updates the displayed text in the drop don, all that is great.
However, when I select a different item from the drop down, the text boxes don't bind to that newly selected item, they stay bound to the old one.
Do I need to remove and re-add my bindings every time the selection changes on the combo box?
My original answer was wrong, and admittedly I do not fully understand what all is happening here, but I have a solution which is working.
Basically you need to grab the BindingManagerBase
from the BindingContext
and use it to enforce databinding on each SelectedItemChanged
event.
public partial class TestForm : Form
{
public DataClassesDataContext DataContext;
public IQueryable<T> datasource;
private BindingManagerBase bmComboBoxSelectedItem;
// Ctor
public TestForm()
{
InitializeComponent();
// L2S data context
this.DataContext = new DataClassesDataContext();
// Get the variable for the data source
this.datasource = this.DataContext.Ts;
// setup the binding for the combobox
this.comboBox1.DataSource = this.datasource;
this.comboBox1.DisplayMember = "Description";
this.comboBox1.ValueMember = "Id";
// assign the databindings of the text boxes to the selectedItem of the combo box
// this is where the problem is, afaik
TId.DataBindings.Add(new Binding("Text", this.comboBox1, "SelectedItem.Id"));
TUser.DataBindings.Add(new Binding("Text", this.comboBox1, "SelectedItem.User"));
TDescription.DataBindings.Add(new Binding("Text", this.comboBox1, "SelectedItem.Description"));
bmComboBoxSelectedItem = this.BindingContext[this.comboBox1, "SelectedItem"];
}
// make sure you assign this event on the forms designer or your preferred method
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
bmCustomers.ResumeBinding();
}
}
This MSDN article helped a lot.
Use a BindingSource rather than directly relying upon the L2S data context. The binding source uses a concurrency manager to handle all the updating for you and the L2S does not
Working code:
public partial class TestForm : Form
{
public DataClassesDataContext DataContext;
// Incorrect: public IQueryable<T> datasource;
// Correct:
public BindingSource TsDataSource;
// Ctor
public TestForm()
{
InitializeComponent();
// L2S data context
this.DataContext = new DataClassesDataContext();
// Get the variable for the data source
// Incorrect: this.datasource = this.DataContext.Ts;
// Correct:
this.TsDataSource = new BindingSource();
this.TsDataSource.DataSource = this.DataContext.Ts;
// setup the binding for the combobox
this.comboBox1.DataSource = this.TsDataSource;
this.comboBox1.DisplayMember = "Description";
this.comboBox1.ValueMember = "Id";
// assign the databindings of the text boxes to the selectedItem of the combo box
TId.DataBindings.Add(new Binding("Text", this.TsDataSource, "Id"));
TUser.DataBindings.Add(new Binding("Text", this.TsDataSource, "User"));
TDescription.DataBindings.Add(new Binding("Text", this.TsDataSource, "Description"));
}
More about BindingSource from the source (couldnt resist):
The BindingSource component serves
many purposes. First, it simplifies
binding controls on a form to data by
providing currency management, change
notification, and other services
between Windows Forms controls and
data sources. This is accomplished by
attaching the BindingSource component
to your data source using the
DataSource property. For complex
binding scenarios you can optionally
set the DataMember property to a
specific column or list in the data
source. You then bind controls to the
BindingSource. All further interaction
with the data is accomplished with
calls to the BindingSource component.
For examples on how the BindingSource
can simplify the binding process, see
How to: Bind Windows Forms Controls to
DBNull Database Values and How to:
Handle Errors and Exceptions that
Occur with Databinding. Navigation and
updating of the data source is
accomplished through methods such as
MoveNext, MoveLast, and Remove.
Operations such as sorting and
filtering are handled through the Sort
and Filter properties. For more
information on using sorting and
filtering with the BindingSource, see
How to: Sort and Filter ADO.NET Data
with the Windows Forms BindingSource
Component.