views:

2650

answers:

3

I have a list box that requires at least one ComboBox. I couldn't find a way to place the ComboBox in the ItemTemplate I use.

... 
<DataTemplate x:Key="parts_template">
  <StackPanel Orientation="Horizontal">
    <TextBlock .../>
    <ComboBox .../>
  </StackPanel>
</DataTemplate>

...
<ListBox x:Name="lb_parts" ItemTemplate="{StaticResource parts_template}" .../>
...

How do bind that ComoBox in the DataTemplate to an ObservableCollection in the code behind?

A: 

Okay, here is how you can add a ComboBox to the ListBox in the code behind.

Create a ComboBox

ComboBox x = new ComboBox();

If you have a data source that populates the ComboBox then you can just bind that

x.ItemsSource = e.Result;

If you do not and want to manually add items to the ComboBox:

ComboBoxItem y = new ComboBoxItem();

Set the Content of the Item to what you want displayed in the ComboBox

y.Content = "Hello";

Now all that is left, is to add the ComboBoxItem to the ComboBox (only if you are creating the Items manually), and then the ComboBox to the ListBox

x.Items.Add(y);

//testing is my ListBox
testing.Items.Add(x);
Johannes
Haven't tried this but I would prefer not to create the combo box itself in the code.
James
+3  A: 

Another thing you could try is subscribe the Loaded event on the ComboBox. Then you can set the ComboBox.ItemsSource in the EventHandler to MyObservableCollection.

Have a look

XAML:

<DataTemplate x:Key="parts_template">
  <StackPanel Orientation="Horizontal">
    <TextBlock .../>
    <ComboBox Loaded="ComboBox_OnLoaded">
        <!-- ComboBox ItemTemplate -->
    </ComboBox>
  </StackPanel>
</DataTemplate>

C# Code Behind:

private void ComboBox_OnLoaded(object sender, EventArgs e)
{
    ((ComboBox)sender).ItemsSource = MyObservableCollection;
}
IrishJoker
This should work for a simple scenario where you have the collection for item source does not change during lifetime of the page.The problems is that the Loaded event gets triggered for every item in the list box. I have to make a call to the server to populate the collection. Since the data used in the combo box depends on another field on the screen and when the user changes the value, I need to change the contents in that drop down. That means the number of calls to the server is same as the number of items in the list box even though I would be making the same call for the same content.
James
When do you make the call to the Server to populate the ObservableCollection.In my example above, this is just setting the ComboBox ItemsSource to the ObservableCollection. Whenever you choose to update the Colletion doesn't matter since the ComboBox will be notified of any changes and reflect that in their Items.At the moment they all share the same ObservableCollection - if this isn't what you want then this solution won't work for you, for the reasons you stated.Hope this makes sense.
IrishJoker
Yes, it did work. Set the collection once when the other field changed and just assign the collection in the Loaded event. I wish I could just refer to another template in the xaml.
James
A: 

You should be able to set the data context to the List itself

lb_Parts.DataContext=myCollection;

Then you should be able to bind to it in the template

<DataTemplate x:Key="parts_template">
   <StackPanel Orientation="Horizontal">
     <TextBlock .../>
     <ComboBox ItemSource={Binding}/>
   </StackPanel>
</DataTemplate>
Jacob Adams
I did not get it. How would that collection look like? Assume the list box has one text block, one check box and a combo box. Right now I have a collection of type x that has one boolean and two text fields.
James