How can I bind a List as ItemSource to ListView in XAML?

25,611

Solution 1

You can only databind to public properties and you need to set the DataContext.

public partial class MainWindow : Window
{
    public ObservableCollection<string> myList { get; private set; }

    public MainWindow()
    {
        InitializeComponent();

        myList = new ObservableCollection<string>();
        myList.Add("first string");
        DataContext = this;
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        myList.Add(textBox1.Text);
        textBox1.Text = myList.Count + "st";
    }
}

Solution 2

The approach selected as an answer works fine... but I don't specifically like having to specify the DataContext programmatically while setting everything else in XAML, I don't feel like it's "proper" (maybe this is just me). So for the next person, or anyone else who thinks like me and finds this off a search engine (like i did), here is the way to do it in XAML:

C#

public sealed partial class MainPage : Page
{
    public ObservableCollection<string> Messages { get; set; }

    public MainPage()
    {
        this.Messages = new ObservableCollection<string>();
        this.InitializeComponent();
    }
}

XAML

<Window
    ....
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    ...>

    <ListView ItemsSource="{Binding Messages}" ... />

</Window>

To be honest I think {Binding RelativeSource={RelativeSource Self}} should be the default value any top level element's (Page, Window, etc...) DataConext because it is simply how a lot of people expect it to work, I know it's how I assume it would work. Honestly, I feel like {Binding RelativeSource={RelativeSource Self}} is a bit verbose and almost long for a shorter syntax.

Share:
25,611
Jonas
Author by

Jonas

Passionated Software Developer interested in Distributed Systems

Updated on July 06, 2020

Comments

  • Jonas
    Jonas almost 4 years

    I'm learning WPF and would like to have a collection similar to a LinkedList, to where I can add and remove strings. And I want to have a ListView that listen to that collection with databinding. How can I do bind a simple list collection to a ListView in XAML?

    My idea (not working) is something like this:

    <Window x:Class="TestApp.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <LinkedList x:Key="myList"></LinkedList> //Wrong
        <Window.Resources>
        <Grid>
        <ListView Height="100" HorizontalAlignment="Left" Margin="88,134,0,0" 
          Name="listView1" VerticalAlignment="Top" Width="120" 
          ItemsSource="{Binding Source={StaticResource myList}}"/> //Wrong
        </Grid>
    </Window>
    

    All my code (updated version, not working):

    <Window x:Class="TestApp.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" 
              Name="textBox1" VerticalAlignment="Top" Width="120" />
            <Button Content="Button" Height="23" HorizontalAlignment="Right" 
              Margin="0,12,290,0" Name="button1" VerticalAlignment="Top" Width="75" 
              Click="button1_Click" />
            <ListView Height="100" HorizontalAlignment="Left" Margin="88,134,0,0" 
              Name="listView1" VerticalAlignment="Top" Width="120" 
              ItemsSource="{Binding myList}"/>
        </Grid>
    </Window>
    

    C#-code:

    namespace TestApp
    {
        public partial class MainWindow : Window
        {
            ObservableCollection<string> myList = new ObservableCollection<string>();
            public MainWindow()
            {
                InitializeComponent();
                myList.Add("first string");
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                myList.Add(textBox1.Text);
                textBox1.Text = myList.Count+"st";
            }
        }
    }