1
votes

I have got a list view and bind ItemSource to public ObservableCollection StockList { get; set; }. I initiated the StoclList in the Constructor method. I am getting filtered stock list from a ViewModel and adding these items to this StcokList but somehow ListView doesn't show the list items.

But if i set ItemsSource="{Binding ListFromViewModel}" It works..

 public partial class MainWindow : Window     {   

    public MainWindowViewModel viewModel;
    public ObservableCollection<StockModel> StockList { get; set; }

    //Constructor
    public MainWindow()
    {
        StockList = new ObservableCollection<StockModel>();
        InitializeComponent();
        viewModel = new MainWindowViewModel();
        this.DataContext = viewModel;           
    }

    private async void BtnSelectFile_Click(object sender, RoutedEventArgs e)
    {
        GetData();
        viewModel.StartProcessing(progress);
        StockList.Clear();
        for (int i = 0; i < viewModel.ListOfStocks.Count; i++)
        {
            StockList.Add(viewModel.ListOfStocks[i]);
        }
    }

And my XAML file is like this

<ListView Grid.Row="1" Grid.Column="1" x:Name="LvErrorList" ItemsSource="{Binding StockList}">

UPDATE: If i use this code, it start working. But I am not sure why!!!

LvErrorList.ItemsSource = StockList;
1
StockList is a property of the MainWindow class, while you set the DataContext to a MainWindowViewModel instance. How is that supposed to work? Did you intend to have the StockList property in MainWindowViewModel? What is the purpose of the view model otherwise? - Clemens
Thank you for your reply, Clemens. So because I set this.DataContext = viewModel; My MainWindow.xaml will ignore all my MainWindow bindings? Bindings only work if i declare it inside the ViewModeClass? - AliAzra
Unless you explicitly set the source object of a Binding, it uses the current DataContext. Not sure if it makes sense, but you could write ItemsSource="{Binding StockList, RelativeSource={RelativeSource AncestorType=Window}}". But the property should of course be in a view model class, when you already have one. - Clemens

1 Answers

1
votes

When you type {Binding StockList} in your XAML markup, WPF will try to bind to the StockList property of the current DataContext of the ListView.

Since the ListView inherits its DataContext from the parent element all the way up to the parent window, it will look for the property in the MainWindowViewModel object which you have set as the DataContext in the constructor of the window.

If you set the DataContext the the instance of a class where the StockList property is defined, i.e. the window itself in this case, your binding will work:

this.DataContext = this;

Alternatively, you could move the StockList property to the view model or opt out of the DataContext by specifying an explicit source for the binding. This will bind to the StockList property of the window itself regardless of the DataContext:

<ListView Grid.Row="1" Grid.Column="1" x:Name="LvErrorList"
    ItemsSource="{Binding StockList, RelativeSource={RelativeSource AncestorType=Window}}">

Please refer to the docs for more information about data binding in WPF and how it works.