Search code examples
c#wpfxamldatagridobservablecollection

Datagrid stays Empty but ObservableCollection has values


Currently i am trying to learn WPF, but i have hit a brickwall with my current Problem, after many hours googling and trying to fix it on my own. I am trying to display the Model Province. I have found multiple similar Problems but i couldn't figure it out on my own. After having checked the Output there was no mention of any error. Currently the Window shows just the empty Model but no data even though the Observable Collection gets updated. So before i completely destroy my interest in WPF i am asking for help.

MyView

<Window x:Class="isnuaatest.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:isnuaatest"
    xmlns:local1="clr-namespace:isnuaatest.Models"
    xmlns:local2="clr-namespace:isnuaatest.ViewModel"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
    <local2:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Grid>
        <DataGrid ItemsSource="{Binding Provinces, UpdateSourceTrigger=PropertyChanged}">
        </DataGrid>
    </Grid>
    <StackPanel Width="200" Margin="50">
        <Button x:Name="OpenSaveFile" Click="OpenSaveFile_Click">OpenSaveFile</Button>
    </StackPanel>
</Grid>

My View Model

using isnuaatest.Helper;
using isnuaatest.Models;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;

namespace isnuaatest.ViewModel
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Province> _province;
        public ObservableCollection<Province> Provinces
        {
            get { return this._province; }
            set
            {
                _province = value;
            }
        }
        public MainWindowViewModel() : base()
        {
            this.Provinces = new ObservableCollection<Province>();
        }

        private string _savegamePath;
        public string SavegamePath
        {
            get { return _savegamePath; }
            set { _savegamePath = value; OnPropertyChanged("SavegamePath"); GetProvinces(_savegamePath);}
        }



        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var savegamefile = this.PropertyChanged;
            if (savegamefile != null)
                savegamefile(this, new PropertyChangedEventArgs(propertyName));
        }
        public event EventHandler OnItemChanged;
        public void GetProvinces(string path)
        {
            Reader reader = new Reader();
            if (_savegamePath != null)
            {
                FileStream fs = File.OpenRead(path);
                List<Province> listofProvinces = reader.ReadTextString(fs);
                foreach (Province province in listofProvinces)
                {
                    Provinces.Add(new Province()
                    {
                        Aristocrats = province.Aristocrats,
                        Artisans = province.Artisans
                    });
                }
            }
        }
    }
}

Code Behind

using isnuaatest.Helper;
using isnuaatest.Models;
using isnuaatest.ViewModel;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
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;

namespace isnuaatest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindowViewModel _vm = new MainWindowViewModel();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
        private void OpenSaveFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Multiselect = false;

            dynamic result = fileDialog.ShowDialog();

            if (result == true)
            {
                _vm.SavegamePath = fileDialog.FileName;
            }
        }
    }
}

My thinking is that maybe the Data Context wont update, because the data is in the Observable Collection. If this is true how can i update the Data Context, i already tried adding it in xaml to no avail.

Thanks


Solution

  • You actually create 3 different MainWindowViewModel objects - one in xaml and two in code behind. You can get rid of one in xaml, once in MainWindow constructor you set DataContext xaml-one is overridden.
    But two objects in code-behind cause your problem - you load file into _vm object, but it's not the one that is held in DataContext.
    To fix your problem use _vm for DataContext and not the new object:

    public MainWindowViewModel _vm = new MainWindowViewModel();
    public MainWindow()
    {
         InitializeComponent();
         DataContext = _vm;
    }