0

I'm having some trouble binding data to a ListView control. I watched many tutorials where it seems like they did it the way I did here with either binding to a collection or a class that had a collection of items.

When I add the cars in this example nothing is added to the listview control. Anything obvious I have missed here? I have checked that the cars are added to the collection during runtime.

enter image description here

The car class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CarClasses
{

    internal class Car
    {
        string _brand = "";
        string _model = "";

        public Car(string brand, string model)
        {
            _brand = brand;
            _model = model; 
        }

        public string Brand
        {
            get { return _brand; }  
            set { _brand = value; }
        }

        public string Model
        { 
            get { return _model; } 
            set { _model = value; }
        }  

    }

}

MainWindow.xaml:

<Window x:Class="GridViewListView.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:GridViewListView"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="600">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="75"></ColumnDefinition>
            <ColumnDefinition Width="2*"></ColumnDefinition>
            <ColumnDefinition Width="7*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ListView x:Name="lvCarList" ItemsSource="{Binding CarCollection }" Grid.Column="2" Width="200" Height="250" SelectionMode="Single" BorderThickness="3" BorderBrush="AliceBlue">
            <ListView.Style>
                <Style/>
            </ListView.Style>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="50"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50"></ColumnDefinition>
                            <ColumnDefinition Width="100"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Label Grid.Row="0" Grid.Column="0" Content="{Binding Brand}"></Label>
                        <Label Grid.Row="0" Grid.Column="1" Content="{Binding Model}"></Label>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <StackPanel Grid.Column="0">
            <TextBlock Text="Brand" Margin="10,10,0,0"></TextBlock>
            <TextBlock Text="Model" Margin="10,10,0,0"></TextBlock>
        </StackPanel>
        <StackPanel  Grid.Column="1" Margin="0,0,0,0">
            <TextBox Name="txtBrand" HorizontalAlignment="Left" Width="100" Margin="10,10,0,0"></TextBox>
            <TextBox Name="txtModel" HorizontalAlignment="Left" Width="100"  Margin="10,10,0,0"></TextBox>
            <Button Name="btnAdd" Content="Add" Margin="10, 10,10,10" Click="btnAdd_Click"></Button>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CarClasses;

namespace GridViewListView
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 


    public partial class MainWindow : Window
    {
        List<Car> CarCollection = new List<Car>();
        public MainWindow()
        {
            InitializeComponent();
                 
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            Car newCar = new Car(txtBrand.Text, txtModel.Text);
            CarCollection.Add(newCar);  
            txtBrand.Text = "";
            txtModel.Text = "";
        }
    }
}
2
  • 1
    List<> does not raise the CollectionChanged event. Use ObservableCollection instead Commented Nov 21, 2021 at 10:57
  • Thanks for the response, but it's the same result using a ObservableCollection. ObservableCollection<Car> CarCollection = new ObservableCollection<Car>(); Commented Nov 21, 2021 at 11:06

1 Answer 1

1

You should/need to specify the DataContext. And you need to make the Car's collection a public property. It's currently a field. And also it should be an ObservableCollection, because it's changed at runtime and changes should be displayed in the UI automatically.

    public partial class MainWindow : Window
    {
        public ObservableCollection<Car> CarCollection { get; } = new ObservableCollection<Car>();
        public MainWindow()
        {
            this.DataContext = this;
            InitializeComponent();
                 
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            Car newCar = new Car(txtBrand.Text, txtModel.Text);
            CarCollection.Add(newCar);  
            txtBrand.Text = "";
            txtModel.Text = "";
        }
    }
Sign up to request clarification or add additional context in comments.

5 Comments

I just did exactly what you suggested but the IDE is giving me an error: Error code: CS0053: https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0053?f1url=%3FappId%3Droslyn%26k%3Dk(CS0053) Inconsistent accessibility: property type 'ObservableCollection<Car>' is less accessible than property 'MainWindow.CarCollection'
I had to make the Car class public as well. Now it works. Thanks for you help!
Hi Mogash. Yes that's exactly right. :)
I have a follow up question regarding the DataContext. Say for instance the car collection was belonging to it's own class in the Cars namespace in a code file as provided in the code samples. Would the DataContext statement still remain the same? Or how would you go forth to reference the collection in a class in another file/namespace?
If Car collection belongs to a different class you would have to change the DataContext to the instance of that class. Also others ways of solving it possible. In general the Path in XAML must resolve, i.e belong to the DataContext. If your project grows you usually have more then 1 ViewModel and then you construct some kind of VM hierarchy, where Sub-ViewModels are nested in/properties of the Main viewmodel and such like. Like Matryoshkas dolls ;) .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.