Search code examples
c#xamlmvvmlistboxwindows-store-apps

Bind ViewModel List<T> to Listbox in C# Windows Universal App


I have a listbox which i want to get updated when the items get added to a list. I understand I need to bind the listbox. I was trying to follow this question/answer.

I have a ViewModel which handles the list:

namespace TESTS
{
public class ViewModel : INotifyPropertyChanged
{
    private List<Cars> _listCars;
    public List<Cars> listCars
    {
        get
        {
            return _listCars;
        }

        set
        {
            if (_listCars == value)
            {
                return;
            }

            this.RaisePropertyChanged("Message");
            _listCars = value;
            this.RaisePropertyChanged("Message");
        }
    }
   public ViewModel()
    {
        listCars = new List<Cars>();
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        Debug.WriteLine("Property Changed");
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
}

Here is the class Cars:

public class Cars: INotifyPropertyChanged
{
    public string model{ get; set; }
    public string year{ get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
}

So I did the binding of listbox to the property path in my Viewmodel which is listCars.

<ListBox .... ItemsSource="{Binding listCars}">

So when in my Main.xaml.cs. I do a button click and add the item. It does not get added to the listbox even though its bind to the list on view model.

public sealed partial class MainPage : Page
{
    public static ViewModel vm = new ViewModel();
    public MainPage()
    {
        this.InitializeComponent();
        this.DataContext = vm;            
    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        Cars x = new Cars();
        x.model = "Ford";
        x.Year = "1998";
        vm.listCars.Add(x);
    }
}

I hope I explained what i implemented well enough. Is there something wrong in my implementation of ViewModel. I am new to MVVM. Please help.


Solution

    1. Use ObservableCollection<T>, not List<T>. The former is designed to be used with MVVM, the latter is not. You'll get all your notifications automatically. It's doable with List<T>, but you'll have to write much more code and the performance will be much worse, especially with big collections. Just don't do it.

    2. If you create the collection in the constructor, assign it to a read-only property and never change its instance (and this is the way you should do it), you don't even need to implement INPC.

    3. When implementing INPC, you're expected to call RaisePropertyChanged after you've changed the property, once, and with the property name that has been changed, not a random unrelated string.