How can I data bind a list of strings to a ListBox in WPF/WP7?
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());
}
Comments
-
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 about 12 yearsThanks, 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 about 12 yearsThat 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 about 12 yearsThanks, 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 about 12 yearsThanks, can you please give me an example for the DataContext? I am having a hard time understanding it.
-
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 over 10 yearsWith
Path=.
being required for two-way bindings -
pt12lol about 9 yearsHelpful 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 about 9 years@pt12lol You're right but with expansion (like using a complex object) in mind I used the template.
-
Paul McCarthy about 4 yearsIt'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.