views:

562

answers:

2

Hi,

I'm databinding a listbox to an object that contains two array of strings. Each listbox item is set to a data template made up of a textbox and a combo box. The first string array is bound to the list, and the second string array is bound to the combo box. Well, at least that's I'm trying to achieve. The problem is that I can't figure out the binding syntax to set the second array to the combo box. Here's what I have:

The first thing is my class with my two string arrays. Pretty straightforward. Please note that the string array content is there for simplicity.

    public class JobAssignments
    {
        public JobAssignments()
        {
            m_people.Add("John");
            m_people.Add("Bill");
            m_people.Add("Frank");
            m_people.Add("Steve");

            m_jobs.Add("Architect");
            m_jobs.Add("Teacher");
            m_jobs.Add("Carpenter");
            m_jobs.Add("Plumber");

        }

        private List<string> m_people = new List<string>();
        public List<string> People { get { return m_people; } set { m_people = value; } }

        private List<string> m_jobs = new List<string>();
        public List<string> Jobs { get { return m_jobs; } set { m_jobs = value; } }
    };

In code, I set an instance of this class as the datacontext of this listbox:

    <ListBox x:Name="listBox"
             Grid.Row="0"
             HorizontalContentAlignment="Stretch"
             DataContext="{Binding}"
             ItemsSource="{Binding People}"
             ItemTemplate="{StaticResource JobAssignmentDataTemplate}">
    </ListBox>

With a data template that looks like this:

<DataTemplate x:Key="JobAssignmentDataTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0"
                           Text="{Binding}"/>
                <ComboBox Grid.Column="2" 
                          SelectedIndex="0" 
                          ItemsSource="{Binding Jobs ???? }"/>
            </Grid>
        </DataTemplate>

What I usually get out my experiments is a list box of People, but the combo box of each list item is empty.

I can get it to work if I use

ItemsSource="{Binding ElementName=listBox, Path=DataContext.Jobs }"/>

but I don't want to use ElementName as it hardcodes the source of the array a specific listbox which I'd like to avoid.

Trying something like

ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=Parent.Jobs}"/>

Doesn't seem to work either as it's looking for Jobs inside the Grid.

A little push in the right direction would help greatly.

Thanks!

A: 

When you are at DataTemplate that represents just one People your JobAssignments instance is not there. Try the below

ItemsSource="{Binding ElementName= listBox, Path=Jobs}"/>

But I dont recommend the above step. You need to refactor your ViewModel logic. I guess 'Jobs' can be a static instance so that you can do a x:Static binding

ItemsSource="{Binding Source={x:Static JobAssignments}, Path=Jobs}"
Jobi Joy
Unfortunately, the list of jobs isn't static in my project, which would've been nice.
Steve the Plant
Then try my first step, ELementName binding to the ListBox
Jobi Joy
A: 

You probably need to modify your object structure to work like this:

public class Person
{
  public string Name;
  public IEnumerable<string> Jobs;
}

public class JobAssignments
{
  public JobAssignments()
  {
    Jobs.Add("Architect");
    ...

    People.Add(new Person() { Name = "Bob", Jobs = Jobs });
    ...
  } 

  private List<Person> m_people = new List<Person>();
  public List<Person> People { get { return m_people; } }

  private List<string> m_jobs = new List<string>();
  public List<string> Jobs { get { return m_jobs; } }
}

Then, you can remove the question marks, and things should work.

John Fisher