Reputation: 330892
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?
Upvotes: 83
Views: 185112
Reputation: 14432
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>
Upvotes: 173
Reputation: 6825
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.
Upvotes: 23
Reputation: 374
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());
}
Upvotes: 6
Reputation: 36775
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.
Upvotes: 9