How can I data bind a list of strings to a ListBox in WPF/WP7?

Joan Venge picture Joan Venge · Feb 22, 2012 · Viewed 142.7k times · Source

I am trying to bind a list of string values to a listbox so that their values are listed line by line. Right now I use this:

<ListBox Margin="20" ItemsSource="{Binding Path=PersonNames}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=Id}"></TextBlock>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

But I don't know what I am supposed to put into the textblock, instead of Id, since they are all string values, not custom classes.

Also it complains not having to find the PersonNames when I have it inside MainPage, as MainPage.PersonNames.

I set the data context to:

DataContext="{Binding RelativeSource={RelativeSource Self}}"

I am doing it wrong?

Answer

Abbas picture Abbas · Feb 22, 2012

If simply put that your ItemsSource is bound like this:

YourListBox.ItemsSource = new List<String> { "One", "Two", "Three" };

Your XAML should look like:

<ListBox Margin="20" Name="YourListBox">
    <ListBox.ItemTemplate> 
        <DataTemplate> 
            <StackPanel Orientation="Horizontal"> 
                <TextBlock Text="{Binding}" /> 
            </StackPanel> 
        </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Update:

This is a solution when using a DataContext. Following code is the viewmodel you will be passing to the DataContext of the page and the setting of the DataContext:

public class MyViewModel
{
    public List<String> Items
    {
        get { return new List<String> { "One", "Two", "Three" }; }
    }
}

//This can be done in the Loaded event of the page:
DataContext = new MyViewModel();

Your XAML now looks like this:

<ListBox Margin="20" ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

The advantage of this approach is that you can put a lot more properties or complex objects in the MyViewModel class and extract them in the XAML. For example to pass a List of Person objects:

public class ViewModel
{
    public List<Person> Items
    {
        get
        {
            return new List<Person>
            {
                new Person { Name = "P1", Age = 1 },
                new Person { Name = "P2", Age = 2 }
            };
        }
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

And the XAML:

<ListBox Margin="20" ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=Name}" />
                <TextBlock Text="{Binding Path=Age}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Hope this helps! :)