views:

582

answers:

2

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?

+1  A: 

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.

NickLarsen
I get this exception "DataMember property 'SelectedItem' cannot be found on the DataSource."
Allen
I've also tried binding to a member variable and onchange on the drop down, i reassign that variable to the currently selected one. That too causes my initial problem. So, I don't think this is the solution I need
Allen
Hopefully these changes will help you get started. I really don't fully understand it yet, but this is what I came up with by playing with it and using the linked MSDN article.
NickLarsen
Awesome, I will follow up on monday for sure, +1 for now, thanks again
Allen
ok so i've since learned to just add the datasource and let the designer wire up all your databindings for you. I'll post some of the code that the designer writes for you.
Allen
A: 

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.

Allen