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

158,697

Solution 1

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! :)

Solution 2

You should show us the Code for PersonNames, and I am not sure, I understand your question, but maybe you want to bind it like this:

<TextBlock Text="{Binding Path=.}"/>

or

<TextBlock Text="{Binding"} />

This will bind to the current element in the list. (Assuming PersonNames is a list of strings). Otherwise, you will see the class name in the list

Solution 3

If the items source is enumerable as string-entries, use the following:

<TextBlock Text="{Binding}"></TextBlock> 

You can use this syntax on any object. Generally, the ToString() -method will then called to get the value. This is in many cases very handy. But beware that no change notification will occur.

Solution 4

You can do this without having to explicitly define the TextBlock control as a part of your ListBox (unless you want better formatting). The trick to getting the binding to trigger is using an ObservableCollection<string> instead of List<string>

Window1.xaml

<ListView Width="250" Height="50" ItemsSource="{Binding MyListViewBinding}"/>

Window1.xaml.cs

public Window1()
{
   InitializeComponent();
   DataContext = this;

   // Need to initialize this, otherwise you get a null exception
   MyListViewBinding = new ObservableCollection<string>();
}

public ObservableCollection<string> MyListViewBinding { get; set; }

// Add an item to the list        
private void Button_Click_Add(object sender, RoutedEventArgs e)
{
   // Custom control for entering a single string
   SingleEntryDialog _Dlg = new SingleEntryDialog();

   // OutputBox is a string property of the custom control
   if ((bool)_Dlg.ShowDialog())
      MyListViewBinding.Add(_Dlg.OutputBox.Trim());
}
Share:
158,697
Joan Venge
Author by

Joan Venge

Professional hitman.

Updated on December 02, 2020

Comments

  • Joan Venge
    Joan Venge over 3 years

    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?

  • Joan Venge
    Joan Venge about 12 years
    Thanks, I am confused by YourListBox. Is it the name of the control? Do you have to the first line in code for the xaml to work?
  • Abbas
    Abbas about 12 years
    That was a typo, it is indeed the Name of the Control. You can also bind the items through a DataContext on your page or through Resources. The binding I gave was for demo-purposes. :)
  • Joan Venge
    Joan Venge about 12 years
    Thanks, I will try this but I am still having an issue with the binding part where it complains not finding PersonNames in xaml.
  • Joan Venge
    Joan Venge about 12 years
    Thanks, can you please give me an example for the DataContext? I am having a hard time understanding it.
  • HCL
    HCL about 12 years
    @Joan Venge: THe binding issue is another problem and not explained rapidly in a comment. I assume that the DataContext of your UserControl or Window is not set to the PersonNames-exposing instance. If it is declared in the Window or UserControl, you can add for a fast solution the following into the binding {Binding PersonNames,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}} where you have to replace "Window" through "UserControl" if your ListBox is within a UserControl. Check out some posts about DataContext and MVVM, this will help you understand the DataContext
  • Dani
    Dani over 10 years
    With Path=. being required for two-way bindings
  • pt12lol
    pt12lol about 9 years
    Helpful answer :) but as far as I noticed it is not necessary to use ListBox.ItemTemplate at all if you use only string instead of complex class. default behaviour just prints it.
  • Abbas
    Abbas about 9 years
    @pt12lol You're right but with expansion (like using a complex object) in mind I used the template.
  • Paul McCarthy
    Paul McCarthy about 4 years
    It's not intuitive and cannot be selected at design time. I've yet to develop anything with xaml without having to come on to SO to find out why it not working.