views:

612

answers:

4

Imagine these two classes:

class Part
{
 public string Name { get; set;}
 public int Id { get; set; }
}

class MainClass
{
 public Part APart { get; set;}
}

How can I bind MainClass to a combo box on a WinForm, so it displays Part.Name (DisplayMember = "Name";) and the selected item of the combo sets the APart property of the MainClass without the need to handle any events on the dropdown.

As far as I know, setting ValueMember of the ComboBox to "Id" means that it will try to set APart to a number (Id) which is not right.

Hope this is clear enough!

A: 

I made a little research and found this article where the author has been able to bind to nested properties by extending the standard binding source component.
I've tried it and it seems to work fine.

Julien Poulin
A: 

What you're looking for is to have the ValueMember (= ComboBox.SelectedItem) be a reference to the object itself, while DisplayMember is a single property of the item, correct? As far as I know, there's no good way to do this without creating your own ComboBox and doing the binding yourself, due to the way ValueMember and DisplayMember work.

But, here's a couple things you can try (assuming you have a collection of Parts somewhere):

  1. Override the `ToString()` method of `Part` to return the `Name` property. Then set your `ComboBox`'s `ValueMember` to `"APart"` and leave `DisplayMember` null. (Untested, so no guarantees)
  2. You can create a new property in Part to return a reference to itself. Set the 'ValueMember' to the new property and 'DisplayMember' to `"Name"`. It may feel like a bit of a hack, but it should work.
  3. Do funny things with your `APart` getter and setter. You'll lose some strong-typing, but if you make `APart` an object and `MainClass` contains the collection of `Part`s, you can set it by `Id` (`int`) or `Part`. (Obviously you'll want to be setting it by Id when you bind the ComboBox to it.)
Part _APart;
object APart 
{ 
    get {return _APart;}
    set {
        if(value is int)
            _APart = MyPartCollection.Where(p=>p.Id==value).Single();
        else if(value is Part)
            _APart = value;
        else
            throw new ArgumentException("Invalid type for APart");
    }
}
lc
A: 

If you set the ValueMember of the combo box to null, the databinding will return the selected item (i.e. the Part instance) instead of speciied member. Set the DisplayMember to 'Name'.

Martin Randall
Can you provide a working snippet of this please? I can't make it to do what you say it does with setting ValueMember to null.
Khash
A: 

create a backing class to hold the "information", and create properties for all the data. Then implement System.ComponentModel.INotifyPropertyChanged on that class, something like:

private String _SelectedPart = String.Empty; 

public String SelectedPart 
{
   get  
   {   
      return _SelectedPart;   
   }  
   set   
   {            
      if (_SelectedPart != value)  
      {
         _SelectedPart  = value;   

         // helper method for handing the INotifyPropertyChanged event
         PropertyHasChanged(); 
      }
   }
}

Then create an "ObjectDataSource" for that class (Shift-Alt-D in VS2008 will bring that up while looking at a form), then click on your ComboBox and set the following properties:

DataSource, set to the ObjectDataSource "BindingSource" you just created. DisplayMember, Set to the Name propertity of the List of parts ValueMember, Set to the ID member of the List of parts DataBindings.SelectedValue, set to the SelectedPart on the "BindingSource" you just created.

I know the above sounds complex, and it might take a bit to find all the parts I just described (wish I could give a tutorial or screenshot), but really it is VERY fast to do once you get used to it.

This is by the way, considered "data-binding" in .NET and there are a few good tutorials out there that can give your more information.

JasonRShaver
Thanks for your post on data-binding. However, this doesn't answer the question which is about binding to the lookup object as opposed to id of the lookup object.
Khash