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

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?

167867 次浏览

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.

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

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

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());
}